mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
92570f5ae10433131f5d52fcf00852f396cf107c
1911
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
92570f5ae1 |
Merge remote-tracking branch 'origin/main' into kennylopez-agent-harness-toggles
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
c4844111f1 |
Normalize fallback runtime identity
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
00ecf2cac7 |
fix(security): authorize kind:9000 role changes in both directions (#3017)
## Summary
NIP-29 `kind:9000` (PUT_USER) role changes were only authorized when the
**new** role was elevated. Demotions were unauthorized, so any
authenticated user could strip a channel owner to `member` with a single
event — and the demotion was unrecoverable, since the ex-owner then
lacked the privilege to restore themselves.
Reported by @Tyler in `#buzz-security`. Verified true, plus two adjacent
defects the report flagged and one it did not.
## The defects
1. **Demotion unauthorized.** The actor check only fired when the
*requested* role was elevated. Lowering someone's role skipped it
entirely.
2. **Open channels skipped the actor check.** It was nested under
`visibility == "private"`.
3. **`add_member` had no last-owner guard** while `remove_member` did —
so a channel could be left with zero owners.
4. **(Not in the report.)** An absent `role` tag defaulted to `Member`,
so a bare self-targeted PUT_USER silently demoted the sender. No
attacker required.
## The fix
**`crates/buzz-db/src/channel.rs`** — the authority, because it also
covers the desktop/admin callers that bypass the relay validator:
- Changing an **active** member's role requires an elevated actor **in
both directions**. Re-adding at the same role stays unguarded and
idempotent (the huddle bot-add and `kind:9021` join paths depend on
this).
- Last-owner guard in `add_member`, mirroring `remove_member`.
- Keyed on the **active** role (`removed_at IS NULL`). A soft-removed
row's role is history, not live authority — otherwise soft-deleted
ownership becomes a resurrection token: a kicked owner self-rejoins via
`9021` and silently regains ownership.
- New `pg_advisory_xact_lock` on a channel-membership namespace, taken
as the first statement in both `add_member` and `remove_member`. Both
read an owner `COUNT` and then write a *different* row, so READ
COMMITTED alone lets two concurrent demotions each observe 2 owners and
together leave 0.
- `remove_member`'s `is_agent_owner` lookup moved before the transaction
opens — it borrows a second pool connection, and issuing it while
holding the lock could self-deadlock on a small pool. Safe because
`agent_owner_pubkey` is immutable (first-mint-wins).
**`crates/buzz-relay/src/handlers/side_effects.rs`**:
- Role tag is now `Option` — absent means "no role change requested"
rather than defaulting to `Member`.
- Actor-role lookup hoisted out of the `visibility == "private"` block,
so open channels are covered.
- Role-change and last-owner guards on every visibility. Rejecting here
*as well as* in the DB means clients get a real error instead of an `OK`
whose side effect then fails silently.
## Verification
**Mutation tested — every guard stubbed individually to confirm a test
actually dies.** Three of eight guards were originally uncovered and
survived being disabled with the suite fully green:
| Guard | Dying test |
|---|---|
| DB actor-auth | *survived* → **new**
`unprivileged_member_cannot_demote_a_co_owner` |
| DB last-owner | `owner_can_still_manage_roles_after_demotion_guard` |
| DB active-role (soft-remove) |
`kicked_owner_rejoins_as_member_not_owner` + 3 |
| `add_member` advisory lock |
`membership_writes_serialize_on_the_shared_channel_lock` |
| `remove_member` advisory lock | +
`remove_member_rejects_an_actor_demoted_while_it_waited` |
| relay no-role-tag preservation |
`test_nip29_put_user_without_role_tag_preserves_role` |
| relay actor-auth | *survived* → **new**
`test_nip29_relay_rejects_role_change_by_unprivileged_actor` |
| relay last-owner | *survived* → **new**
`test_nip29_relay_rejects_last_owner_self_demotion` |
The three gaps shared one cause: every existing test asserts resulting
**state** ("the role did not change"), and the DB guards enforce that
state, masking every layer above them. With a relay guard stubbed the
relay answers `accepted:true` and logs `Side effect failed: access
denied: ...` while the state assertion still passes — the entire relay
validator could be deleted unnoticed. The new relay tests assert
`accepted == false` instead, the one observable only the validator
controls. Each new test is verified in both directions: green against
the real fix, failing with its intended message when its guard alone is
stubbed.
**Test runs** (at `9461eedb`):
- `buzz-db`, serial: **210 passed / 3 failed** — the same 3 failures as
clean `main` (202/3), which are pre-existing and unrelated
(`concurrent_same_owner_create…`,
`create_community_with_owner_is_atomic…`,
`test_usage_metrics_lock_has_single_owner…`). +8 = the new tests.
- `e2e_relay --ignored`: **40 passed / 3 failed**. Clean `main` on the
same relay is 35/6 — the same 3 infra failures
(`test_invite_mint_and_claim…`, `test_subscription_limit_enforced`,
`test_unarchive_emits_member_added_notification`) plus the 3 security
tests that fail unpatched and pass here.
- `cargo fmt`, `clippy`, `git diff --check` all clean.
**Live manual drive** against a locally running relay, using raw
`nak`-signed events (the `buzz` CLI refuses malformed `kind:9000`, so
the guards have to be exercised directly):
- *Rejected:* member demotes owner; member demotes admin; self-promote
to owner; self-promote to admin; admin demotes the last owner; sole
owner self-demote; demoted ex-owner demotes last owner; private-channel
member demotes owner; non-member demotes owner in private.
- *Allowed:* bare PUT_USER with no role tag (owner keeps role);
idempotent re-add at same role; owner promotes admin→owner, then owner2
legitimately demotes owner1.
- *Resurrection defeated:* owner promotes attacker to admin → kicks them
(`9001`) → attacker self-rejoins (`9021`) → returns as **member**, not
admin, and cannot demote the owner.
- Normal ops unaffected throughout: channel creation, messaging, member
listing, and legitimate governance all work.
## Behavior change to be aware of
Huddle bot-add sends `role="bot"`. If the target is **already an active
member at a different role**, that is now a role change and requires an
elevated actor. Previously it silently re-roled them — the same privesc
primitive through a different door, so narrowing it is intended.
This does not break the huddle flow in the path that matters: the
ephemeral channel add (the one that fails hard) is performed by the
host, who *created* that channel and is therefore its owner — verified
live. The parent-channel add is already explicitly best-effort,
capturing the error into `parent_error` with a comment anticipating "may
already be member"; adding a non-member agent there still works.
Flagging it rather than burying it.
## Notes
- Commit is **signoff-only, not cryptographically signed** — `-S` fails
in this environment (git tries to load the agent npub as an SSH key
file). DCO trailers are present and correct.
- Branch was merged with `origin/main` via `--no-ff` (not rebased).
Upstream had 17 commits, none touching these files, no migration
changes.
---------
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
|
||
|
|
c5c4f390b6 |
feat(desktop): handle project work from Inbox (#3117)
## Summary Pull requests and issues that mention you now appear as repository-scoped Inbox conversations, so project work can be reviewed without first navigating to Projects. Opening a project item resolves its current canonical state and reuses the existing review, comment, merge, and issue actions. Repository-aware grouping keeps identical event IDs from different repositories separate, while loading, missing-data, and partial-query states avoid exposing stale actions. ### Related issue None found. ### Testing - `node --import ./test-loader.mjs --experimental-strip-types --test src/features/home/lib/projectInbox.test.mjs` — 6 tests passed - `CI=1 pnpm exec playwright test tests/e2e/project-inbox.spec.ts --project=smoke` — passed - Pre-push desktop, mobile, Tauri, and Rust checks — passed --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com> |
||
|
|
87b3fcd3c0 |
fix(desktop): clarify identity key button when key exists (#2357)
## Summary - backing out of the backup step and clicking the CTA again reuses the existing key - the button still said "Create a new identity key", which is misleading for a security-sensitive action - when a key is already loaded, label it "Continue with existing identity key" Closes #2318 ## Test plan - [ ] first-run: button still says "Create a new identity key" - [ ] create key → backup → back: button says "Continue with existing identity key" and shows the same key Made with [Cursor](https://cursor.com) --------- Signed-off-by: Taksh <takshkothari09@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
b8178d5cba |
Preserve harness merge resolutions after DCO rebase
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
cf55e5ab24 |
Fix global config clippy fixtures
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
f60e7b4979 |
Hide disabled runtimes during setup
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
2a7ab3b542 |
Mask hidden harness effort defaults
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
e525ee1a7d |
Avoid unused override export
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
fdc1ef2c6d |
Distinguish implicit harness fallback pins
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
7b46102d04 |
Wait for loaded agent defaults before welcome kickoff
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
2a8a7bc773 |
Align hidden harness fallback readiness
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
7f6819ee84 |
Respect hidden harnesses during onboarding
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
c1c262b6c5 |
Handle hidden runtimes during Welcome kickoff
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
048d34c526 |
Preserve hidden Welcome runtime aliases
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
64cd41500b |
Filter hidden runtimes from welcome readiness
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
6e81545168 |
Filter hidden harnesses from remaining pickers
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
17329c4227 |
Use harness labels for current options
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
d3e74c33d8 |
Fix harness visibility smoke fixture
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
626f85e432 |
Address harness visibility review feedback
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
1b91579af6 |
Complete hidden harness provisioning policy
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
711ef24222 |
Preserve visible harness fallbacks
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
16c9f8c1ad |
Block hidden harness provisioning bypasses
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
dcc29c5cbf |
Fix hidden agent harness fallbacks
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
9901cf621e |
Scope hidden harness defaults by dialog mode
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
2864db1ca7 |
Filter implicit runtime fallbacks centrally
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
a392ee1f65 |
Preserve hidden harness defaults when editing
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
6e2950029e |
Preserve explicit hidden harness starts
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
6bebda4f07 |
Apply harness visibility to every agent start
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
0591b50b6f |
Scope defaults to visible harness fallbacks
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
81fe1896e5 |
Honor harness visibility for implicit starts
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
4b7a817eb5 |
Keep hidden harness defaults in sync
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
f07dfcfd91 |
Allow hiding agent harness options
Signed-off-by: kenny lopez <klopez4212@gmail.com> |
||
|
|
7fc0cc82db |
Restore Goose and Buzz Agent to onboarding harness selection (#2731)
> [!NOTE] > **Part 1 of a multi-PR onboarding rework.** This PR only restores the hidden harnesses, adjusts the card layout, and gates onboarding completion on valid config. A follow-up PR (stacked on this branch) restructures the flow: the harness page becomes a single-choice "pick your default harness" step, and install/sign-in/provider setup moves to the following page. Review this one on its own terms — the flow rework is intentionally not here. ## Summary - Restore **Goose** and **Buzz Agent** to onboarding harness selection, reverting the launch-only restriction from #2233 - The restore is the single centralized allowlist (`ONBOARDING_RUNTIME_ORDER` in `onboardingRuntimeSelection.ts`) that #2233 deliberately set up for this moment — setup cards, readiness handoff, and the defaults harness picker all derive from it - Lay the four harness cards out as a single row at `lg` and above (`lg:grid-cols-4`); below 1024px (including the app's 800px minimum window width) the grid is 2×2, and 1-up on narrow viewports - **Gate onboarding Finish on actual config validity** (review finding): the defaults page rendered provider/model/credential fields for provider-required harnesses but Finish only checked that a harness was selected — a fresh user picking Buzz Agent could persist a default that fails at first spawn. The Finish gate now consumes `AgentConfigFields`' existing `onValidityChange` signal. Baked build env and runtime-file config satisfy the gate, so internal builds and existing Goose users are never blocked - Update the unit + E2E specs that pinned the hidden behavior, plus two new E2E cases pinning the Finish gate (blocked-until-configured, and baked-env never blocked) - AGENTS.md rule 7 updated to document the completion gate ## Testing - `onboardingRuntimeSelection.test.mjs` — 4 passed - `pnpm typecheck` — clean - `pnpm exec playwright test tests/e2e/onboarding-agent-defaults.spec.ts --project=smoke` — 21 passed - `onboarding-docked-cta-screenshots.spec.ts` — 3 passed - Biome — clean ## Known cosmetic issue (deferred to PR 2) At the app's minimum window size (800×500) the 2×2 grid extends past the visible area and the footer CTA overlaps card space. Next still hit-tests correctly. PR 2 redesigns this page entirely (cards become a single-choice chooser with no inline setup), so this is deferred rather than patched twice. --------- Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com> |
||
|
|
3742076434 |
fix(mobile): mitigate message-post delay with optimistic rendering (#3037)
### What changed? Adds optimistic rendering for newly locally posted messages in channels and threads. - Messages appear immediately - Relay echoes and history are deduplicated by event ID - Rejected or timed-out publishes erase the optimistic rendering. The implementation covers reconnect and hydration races, channel-window and legacy WebSocket paths, thread-local overlays, and rapid concurrent sends. ### Why? This is a valuable partial mitigation for [BOT-1449](https://linear.app/squareup/issue/BOT-1449/buzz-mobile-posted-messages-dont-appear-until-leavingre-entering-the): senders no longer depend on receiving a relay echo before seeing their own post. It does not address the likely primary cause of stale channels. Mobile currently does not recover live subscriptions after a rate-limited relay `CLOSED`; that recovery is being handled separately. ### How is it tested? Full mobile suite: 676 passed, 1 skipped. Added regression coverage for optimistic insertion, authoritative deduplication, rollback, reconnect and hydration, thread replies, rapid and equal-time sends, never-echoed successful sends, and legacy WebSocket retirement. --------- Signed-off-by: npub102wg7q285p64ch2fjvstmf2ntn2sz3c4u5hmwatalc76mhsuauysftjtfj <7a9c8f0147a0755c5d499320bda5535cd5014715e52fb7757dfe3dadde1cef09@buzz.block.builderlab.xyz> Co-authored-by: npub102wg7q285p64ch2fjvstmf2ntn2sz3c4u5hmwatalc76mhsuauysftjtfj <7a9c8f0147a0755c5d499320bda5535cd5014715e52fb7757dfe3dadde1cef09@buzz.block.builderlab.xyz> |
||
|
|
afb272bb7b |
fix(desktop): render rich project work item content (#3100)
## Summary Project issues, pull requests, reviews, and commit details no longer flatten rich content into inert or plain text. They now share the message markdown and media pipeline, preserving NIP-92 `imeta` metadata so links, images, and videos render consistently. Commit bodies are fetched only when a single-commit detail view is opened, keeping list queries lightweight while exposing full context beside the diff. ### Related issue None found. ### Testing - Pre-push suite: `desktop-check`, `desktop-test`, `desktop-tauri-test`, `rust-tests`, and `mobile-test` - Project issue and pull request regression tests cover preserving attachment metadata on roots, updates, and comments - The project commit detail smoke scenario verifies linked text, images, and video in commit bodies Signed-off-by: Thomas Petersen <thomasp@squareup.com> |
||
|
|
070fb6a161 |
chore(deps): update radix-ui-primitives monorepo (#3063)
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@radix-ui/react-alert-dialog](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/alert-dialog)) | [`1.1.19` → `1.1.23`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-alert-dialog/1.1.19/1.1.23) |  |  | | [@radix-ui/react-checkbox](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/checkbox)) | [`1.3.7` → `1.3.11`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-checkbox/1.3.7/1.3.11) |  |  | | [@radix-ui/react-dialog](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/dialog)) | [`1.1.19` → `1.1.23`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-dialog/1.1.19/1.1.23) |  |  | | [@radix-ui/react-dismissable-layer](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/dismissable-layer)) | [`1.1.15` → `1.1.19`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-dismissable-layer/1.1.15/1.1.19) |  |  | | [@radix-ui/react-dropdown-menu](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/dropdown-menu)) | [`2.1.20` → `2.1.24`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-dropdown-menu/2.1.20/2.1.24) |  |  | | [@radix-ui/react-focus-scope](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/focus-scope)) | [`1.1.12` → `1.1.16`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-focus-scope/1.1.12/1.1.16) |  |  | | [@radix-ui/react-popover](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/popover)) | [`1.1.19` → `1.1.23`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-popover/1.1.19/1.1.23) |  |  | | [@radix-ui/react-separator](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/separator)) | [`1.1.11` → `1.1.15`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-separator/1.1.11/1.1.15) |  |  | | [@radix-ui/react-slot](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/slot)) | [`1.3.0` → `1.3.3`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-slot/1.3.0/1.3.3) |  |  | | [@radix-ui/react-tabs](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/tabs)) | [`1.1.17` → `1.1.21`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-tabs/1.1.17/1.1.21) |  |  | | [@radix-ui/react-toggle](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/toggle)) | [`1.1.14` → `1.1.18`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-toggle/1.1.14/1.1.18) |  |  | | [@radix-ui/react-tooltip](https://radix-ui.com/primitives) ([source](https://redirect.github.com/radix-ui/primitives/tree/HEAD/packages/react/tooltip)) | [`1.2.12` → `1.2.16`](https://renovatebot.com/diffs/npm/@radix-ui%2freact-tooltip/1.2.12/1.2.16) |  |  | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/1) for more information. --- ### Release Notes <details> <summary>radix-ui/primitives (@​radix-ui/react-alert-dialog)</summary> ### [`v1.1.23`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/alert-dialog/CHANGELOG.md#1123) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-context@1.2.2`, `@radix-ui/react-dialog@1.1.23`, `@radix-ui/react-primitive@2.1.10` ### [`v1.1.22`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/alert-dialog/CHANGELOG.md#1122) - Updated dependencies: `@radix-ui/react-dialog@1.1.22`, `@radix-ui/react-primitive@2.1.9` ### [`v1.1.21`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/alert-dialog/CHANGELOG.md#1121) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-context@1.2.1`, `@radix-ui/react-dialog@1.1.21`, `@radix-ui/react-primitive@2.1.8` ### [`v1.1.20`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/alert-dialog/CHANGELOG.md#1120) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-dialog@1.1.20`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-context@1.2.0`, `@radix-ui/react-primitive@2.1.7` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-checkbox)</summary> ### [`v1.3.11`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/checkbox/CHANGELOG.md#1311) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-context@1.2.2`, `@radix-ui/react-presence@1.1.10`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-use-controllable-state@1.2.6`, `@radix-ui/react-use-size@1.1.4` ### [`v1.3.10`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/checkbox/CHANGELOG.md#1310) - Updated dependencies: `@radix-ui/react-primitive@2.1.9` ### [`v1.3.9`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/checkbox/CHANGELOG.md#139) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-context@1.2.1`, `@radix-ui/react-presence@1.1.9`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-use-controllable-state@1.2.5`, `@radix-ui/react-use-size@1.1.3` ### [`v1.3.8`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/checkbox/CHANGELOG.md#138) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Fixed a bug where updating a `Checkbox`, `Switch`, or `RadioGroup` value programmatically (eg. a "select all" control) while inside a `<form>` would dispatch a `click` event from the hidden bubble input that propagated to ancestor `onClick` handlers. - Updated dependencies: `@radix-ui/react-presence@1.1.8`, `@radix-ui/react-use-controllable-state@1.2.4`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-context@1.2.0`, `@radix-ui/react-primitive@2.1.7`, `@radix-ui/react-use-size@1.1.2` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-dialog)</summary> ### [`v1.1.23`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dialog/CHANGELOG.md#1123) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-context@1.2.2`, `@radix-ui/react-dismissable-layer@1.1.19`, `@radix-ui/react-focus-guards@1.1.6`, `@radix-ui/react-focus-scope@1.1.16`, `@radix-ui/react-id@1.1.4`, `@radix-ui/react-portal@1.1.17`, `@radix-ui/react-presence@1.1.10`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-slot@1.3.3`, `@radix-ui/react-use-controllable-state@1.2.6`, `@radix-ui/react-use-layout-effect@1.1.4` ### [`v1.1.22`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dialog/CHANGELOG.md#1122) - Updated dependencies: `@radix-ui/react-slot@1.3.2`, `@radix-ui/react-primitive@2.1.9`, `@radix-ui/react-dismissable-layer@1.1.18`, `@radix-ui/react-focus-scope@1.1.15`, `@radix-ui/react-portal@1.1.16` ### [`v1.1.21`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dialog/CHANGELOG.md#1121) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-context@1.2.1`, `@radix-ui/react-dismissable-layer@1.1.17`, `@radix-ui/react-focus-guards@1.1.5`, `@radix-ui/react-focus-scope@1.1.14`, `@radix-ui/react-id@1.1.3`, `@radix-ui/react-portal@1.1.15`, `@radix-ui/react-presence@1.1.9`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-slot@1.3.1`, `@radix-ui/react-use-controllable-state@1.2.5`, `@radix-ui/react-use-layout-effect@1.1.3` ### [`v1.1.20`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dialog/CHANGELOG.md#1120) - Fixed broken ARIA references in Dialogs where a title or description elements are not rendered. - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-dismissable-layer@1.1.16`, `@radix-ui/react-focus-scope@1.1.13`, `@radix-ui/react-portal@1.1.14`, `@radix-ui/react-presence@1.1.8`, `@radix-ui/react-use-controllable-state@1.2.4`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-context@1.2.0`, `@radix-ui/react-focus-guards@1.1.4`, `@radix-ui/react-id@1.1.2`, `@radix-ui/react-primitive@2.1.7`, `@radix-ui/react-slot@1.3.0`, `@radix-ui/react-use-layout-effect@1.1.2` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-dismissable-layer)</summary> ### [`v1.1.19`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dismissable-layer/CHANGELOG.md#1119) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-use-callback-ref@1.1.4`, `@radix-ui/react-use-effect-event@0.0.5` ### [`v1.1.18`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dismissable-layer/CHANGELOG.md#1118) - Updated dependencies: `@radix-ui/react-primitive@2.1.9` ### [`v1.1.17`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dismissable-layer/CHANGELOG.md#1117) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-use-callback-ref@1.1.3`, `@radix-ui/react-use-effect-event@0.0.4` ### [`v1.1.16`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dismissable-layer/CHANGELOG.md#1116) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/primitive@1.1.6`, `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-primitive@2.1.7`, `@radix-ui/react-use-callback-ref@1.1.2`, `@radix-ui/react-use-effect-event@0.0.3` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-dropdown-menu)</summary> ### [`v2.1.24`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dropdown-menu/CHANGELOG.md#2124) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-context@1.2.2`, `@radix-ui/react-id@1.1.4`, `@radix-ui/react-menu@2.1.24`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-use-controllable-state@1.2.6` ### [`v2.1.23`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dropdown-menu/CHANGELOG.md#2123) - Updated dependencies: `@radix-ui/react-menu@2.1.23`, `@radix-ui/react-primitive@2.1.9` ### [`v2.1.22`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dropdown-menu/CHANGELOG.md#2122) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-context@1.2.1`, `@radix-ui/react-id@1.1.3`, `@radix-ui/react-menu@2.1.22`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-use-controllable-state@1.2.5` ### [`v2.1.21`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/dropdown-menu/CHANGELOG.md#2121) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-menu@2.1.21`, `@radix-ui/react-use-controllable-state@1.2.4`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-context@1.2.0`, `@radix-ui/react-id@1.1.2`, `@radix-ui/react-primitive@2.1.7` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-focus-scope)</summary> ### [`v1.1.16`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/focus-scope/CHANGELOG.md#1116) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-use-callback-ref@1.1.4` ### [`v1.1.15`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/focus-scope/CHANGELOG.md#1115) - Updated dependencies: `@radix-ui/react-primitive@2.1.9` ### [`v1.1.14`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/focus-scope/CHANGELOG.md#1114) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-use-callback-ref@1.1.3` ### [`v1.1.13`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/focus-scope/CHANGELOG.md#1113) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-primitive@2.1.7`, `@radix-ui/react-use-callback-ref@1.1.2` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-popover)</summary> ### [`v1.1.23`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/popover/CHANGELOG.md#1123) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-context@1.2.2`, `@radix-ui/react-dismissable-layer@1.1.19`, `@radix-ui/react-focus-guards@1.1.6`, `@radix-ui/react-focus-scope@1.1.16`, `@radix-ui/react-id@1.1.4`, `@radix-ui/react-popper@1.3.7`, `@radix-ui/react-portal@1.1.17`, `@radix-ui/react-presence@1.1.10`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-slot@1.3.3`, `@radix-ui/react-use-controllable-state@1.2.6` ### [`v1.1.22`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/popover/CHANGELOG.md#1122) - Updated dependencies: `@radix-ui/react-slot@1.3.2`, `@radix-ui/react-primitive@2.1.9`, `@radix-ui/react-dismissable-layer@1.1.18`, `@radix-ui/react-focus-scope@1.1.15`, `@radix-ui/react-popper@1.3.6`, `@radix-ui/react-portal@1.1.16` ### [`v1.1.21`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/popover/CHANGELOG.md#1121) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-context@1.2.1`, `@radix-ui/react-dismissable-layer@1.1.17`, `@radix-ui/react-focus-guards@1.1.5`, `@radix-ui/react-focus-scope@1.1.14`, `@radix-ui/react-id@1.1.3`, `@radix-ui/react-popper@1.3.5`, `@radix-ui/react-portal@1.1.15`, `@radix-ui/react-presence@1.1.9`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-slot@1.3.1`, `@radix-ui/react-use-controllable-state@1.2.5`, `@radix-ui/react-use-layout-effect@1.1.3` ### [`v1.1.20`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/popover/CHANGELOG.md#1120) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-popper@1.3.4`, `@radix-ui/react-dismissable-layer@1.1.16`, `@radix-ui/react-focus-scope@1.1.13`, `@radix-ui/react-portal@1.1.14`, `@radix-ui/react-presence@1.1.8`, `@radix-ui/react-use-controllable-state@1.2.4`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-context@1.2.0`, `@radix-ui/react-focus-guards@1.1.4`, `@radix-ui/react-id@1.1.2`, `@radix-ui/react-primitive@2.1.7`, `@radix-ui/react-slot@1.3.0` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-separator)</summary> ### [`v1.1.15`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/separator/CHANGELOG.md#1115) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-primitive@2.1.10` ### [`v1.1.14`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/separator/CHANGELOG.md#1114) - Updated dependencies: `@radix-ui/react-primitive@2.1.9` ### [`v1.1.13`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/separator/CHANGELOG.md#1113) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/react-primitive@2.1.8` ### [`v1.1.12`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/separator/CHANGELOG.md#1112) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-primitive@2.1.7` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-slot)</summary> ### [`v1.3.3`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/slot/CHANGELOG.md#132-133) - Reverted breaking changes that caused compatibility issues with React Server Components. ### [`v1.3.2`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/slot/CHANGELOG.md#132-133) - Reverted breaking changes that caused compatibility issues with React Server Components. ### [`v1.3.1`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/slot/CHANGELOG.md#131) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-tabs)</summary> ### [`v1.1.21`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tabs/CHANGELOG.md#1121) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-context@1.2.2`, `@radix-ui/react-direction@1.1.4`, `@radix-ui/react-id@1.1.4`, `@radix-ui/react-presence@1.1.10`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-roving-focus@1.1.19`, `@radix-ui/react-use-controllable-state@1.2.6` ### [`v1.1.20`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tabs/CHANGELOG.md#1120) - Updated dependencies: `@radix-ui/react-primitive@2.1.9`, `@radix-ui/react-roving-focus@1.1.18` ### [`v1.1.19`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tabs/CHANGELOG.md#1119) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-context@1.2.1`, `@radix-ui/react-direction@1.1.3`, `@radix-ui/react-id@1.1.3`, `@radix-ui/react-presence@1.1.9`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-roving-focus@1.1.17`, `@radix-ui/react-use-controllable-state@1.2.5` ### [`v1.1.18`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tabs/CHANGELOG.md#1118) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-presence@1.1.8`, `@radix-ui/react-roving-focus@1.1.16`, `@radix-ui/react-use-controllable-state@1.2.4`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-context@1.2.0`, `@radix-ui/react-direction@1.1.2`, `@radix-ui/react-id@1.1.2`, `@radix-ui/react-primitive@2.1.7` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-toggle)</summary> ### [`v1.1.18`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/toggle/CHANGELOG.md#1118) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-use-controllable-state@1.2.6` ### [`v1.1.17`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/toggle/CHANGELOG.md#1117) - Updated dependencies: `@radix-ui/react-primitive@2.1.9` ### [`v1.1.16`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/toggle/CHANGELOG.md#1116) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-use-controllable-state@1.2.5` ### [`v1.1.15`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/toggle/CHANGELOG.md#1115) - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-use-controllable-state@1.2.4`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-primitive@2.1.7` </details> <details> <summary>radix-ui/primitives (@​radix-ui/react-tooltip)</summary> ### [`v1.2.16`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tooltip/CHANGELOG.md#1216) - Reverted breaking changes that caused compatibility issues with React Server Components. - Updated dependencies: `@radix-ui/react-compose-refs@1.1.5`, `@radix-ui/react-context@1.2.2`, `@radix-ui/react-dismissable-layer@1.1.19`, `@radix-ui/react-id@1.1.4`, `@radix-ui/react-popper@1.3.7`, `@radix-ui/react-portal@1.1.17`, `@radix-ui/react-presence@1.1.10`, `@radix-ui/react-primitive@2.1.10`, `@radix-ui/react-slot@1.3.3`, `@radix-ui/react-use-controllable-state@1.2.6`, `@radix-ui/react-use-layout-effect@1.1.4`, `@radix-ui/react-visually-hidden@1.2.11` ### [`v1.2.15`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tooltip/CHANGELOG.md#1215) - Updated dependencies: `@radix-ui/react-slot@1.3.2`, `@radix-ui/react-primitive@2.1.9`, `@radix-ui/react-dismissable-layer@1.1.18`, `@radix-ui/react-popper@1.3.6`, `@radix-ui/react-portal@1.1.16`, `@radix-ui/react-visually-hidden@1.2.10` ### [`v1.2.14`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tooltip/CHANGELOG.md#1214) - Republish through CI to attach provenance attestations. The previous versions of these packages were published manually outside of CI and therefore shipped without provenance; this patch re-releases the same code through the CI pipeline so every package includes an attestation. - Updated dependencies: `@radix-ui/primitive@1.1.7`, `@radix-ui/react-compose-refs@1.1.4`, `@radix-ui/react-context@1.2.1`, `@radix-ui/react-dismissable-layer@1.1.17`, `@radix-ui/react-id@1.1.3`, `@radix-ui/react-popper@1.3.5`, `@radix-ui/react-portal@1.1.15`, `@radix-ui/react-presence@1.1.9`, `@radix-ui/react-primitive@2.1.8`, `@radix-ui/react-slot@1.3.1`, `@radix-ui/react-use-controllable-state@1.2.5`, `@radix-ui/react-use-layout-effect@1.1.3`, `@radix-ui/react-visually-hidden@1.2.9` ### [`v1.2.13`](https://redirect.github.com/radix-ui/primitives/blob/HEAD/packages/react/tooltip/CHANGELOG.md#1213) - Fixed a bug where `Tooltip.Content` children were mounted to the DOM twice. - Improved tree-shaking so bundlers can drop unused components. Component parts are now marked `/* @​__PURE__ */` and use named render functions instead of `Component.displayName = ...` assignments, which previously prevented dead-code elimination with some bundlers. - Updated dependencies: `@radix-ui/react-popper@1.3.4`, `@radix-ui/react-dismissable-layer@1.1.16`, `@radix-ui/react-portal@1.1.14`, `@radix-ui/react-presence@1.1.8`, `@radix-ui/react-visually-hidden@1.2.8`, `@radix-ui/react-use-controllable-state@1.2.4`, `@radix-ui/primitive@1.1.6`, `@radix-ui/react-compose-refs@1.1.3`, `@radix-ui/react-context@1.2.0`, `@radix-ui/react-id@1.1.2`, `@radix-ui/react-primitive@2.1.7`, `@radix-ui/react-slot@1.3.0`, `@radix-ui/react-use-layout-effect@1.1.2` </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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
63c62fcf3e |
chore(deps): update dependency @tanstack/react-virtual to v3.14.8 (#3057)
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.6` → `3.14.8`](https://renovatebot.com/diffs/npm/@tanstack%2freact-virtual/3.14.6/3.14.8) |  |  | --- > [!WARNING] > Some dependencies could not be looked up. Check the [Dependency Dashboard](../issues/1) for more information. --- ### Release Notes <details> <summary>TanStack/virtual (@​tanstack/react-virtual)</summary> ### [`v3.14.8`](https://redirect.github.com/TanStack/virtual/blob/HEAD/packages/react-virtual/CHANGELOG.md#3148) [Compare Source](https://redirect.github.com/TanStack/virtual/compare/@tanstack/react-virtual@3.14.7...@tanstack/react-virtual@3.14.8) ##### Patch Changes - [#​1237](https://redirect.github.com/TanStack/virtual/pull/1237) [`aa536e7`](https://redirect.github.com/TanStack/virtual/commit/aa536e7746a88d9f55ca8a4b50d2f548a888fea6) - Fix a gap at the top of the list after an end-anchored prepend in `directDomUpdates` mode. The prepend grows the total size and bumps `scrollOffset` to the new bottom in the same pass, but the size container's height was written *after* `_willUpdate` synced the scroll position — so the browser clamped the `scrollTop` write to the stale (shorter) `scrollHeight`, leaving whitespace at the top until the next scroll. The container is now grown before the scroll sync. Only affected `directDomUpdates` mode (React-rendered sizers receive their height during render). - Updated dependencies \[[`7ae32b5`](https://redirect.github.com/TanStack/virtual/commit/7ae32b55887fd044a48c788546cd940279b338e0)]: - [@​tanstack/virtual-core](https://redirect.github.com/tanstack/virtual-core)@​3.17.6 ### [`v3.14.7`](https://redirect.github.com/TanStack/virtual/blob/HEAD/packages/react-virtual/CHANGELOG.md#3147) [Compare Source](https://redirect.github.com/TanStack/virtual/compare/@tanstack/react-virtual@3.14.6...@tanstack/react-virtual@3.14.7) ##### Patch Changes - Updated dependencies \[[`1e3b908`](https://redirect.github.com/TanStack/virtual/commit/1e3b908705e04e45be2615f2277580cb09f5cdef), [`7dcfc07`](https://redirect.github.com/TanStack/virtual/commit/7dcfc07b877479697124157d3124c09537b87a75)]: - [@​tanstack/virtual-core](https://redirect.github.com/tanstack/virtual-core)@​3.17.5 </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:eyJjcmVhdGVkSW5WZXIiOiI0My4yODAuMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4MC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> |
||
|
|
95fdf97880 |
feat(acp): bring your own harness (BYOH) — generic ACP runtime seam + settings gallery (#2773)
## What
Implements a "bring your own harness" (BYOH) generic ACP mechanism —
replacing per-harness backend code with a data-driven 3-tier system:
- **Tier 1 (compiled-in builtins):** goose, claude, codex, buzz-agent —
unchanged behavior
- **Tier 2 (bundled presets):** cursor, omp, grok, opencode, kimi, amp,
hermes, openclaw, and any future additions — defined in
`PRESET_HARNESSES`, no code duplication, icons stay
TerminalSquare/bundled-asset-only
- **Tier 3 (user-defined custom):** JSON definitions saved to
`custom_harnesses/` under app data; managed via Settings → Agents UI
## Changes
### Core data model
- `HarnessDefinition` — id, label, command, args, env, install URL/hint
- `PRESET_HARNESSES` static table — single source of truth for all
presets; `preset_harness_ids()` derives reserved IDs (D-11: no
hand-maintained copy)
- `source: "builtin" | "preset" | "custom"` tagging on every catalog
entry
### Persistence (B-4, B-6)
- `save_custom_harness_to_dir(dir, definition, rename_old_id)` —
backup-swap atomic write (backs up target → .bak, commits temp → target,
restores .bak on failure, removes .bak on success); safe on Windows
where `fs::rename` over an existing file is "access denied"
- `save_and_warm` / `delete_and_warm` — hold `PERSIST_MUTEX` for the
write + registry-warm pair, eliminating the lost-update race (B-6) where
two concurrent saves could interleave their warm calls and leave a stale
registry snapshot
- Validate-before-mutate: both IDs and env validated before any
filesystem mutation
### Env validation boundary (B-3)
- `validate_harness_definition_pub` calls `validate_user_env_keys` on
definition env at save AND load
- Rejects malformed keys (BUZZ_AUTH_TAG=x forgery shape), reserved keys
(BUZZ_MANAGED_AGENT etc.), NUL bytes, oversized values
### TypeScript boundary (B-2 / Thufir CRITICAL)
- `RawAcpRuntimeCatalogEntry` now declares `definition_env?:
Record<string,string>` and `source: "builtin" | "preset" | "custom"`
- `fromRawAcpRuntimeCatalogEntry` maps `definition_env → definitionEnv`
(camelCase); absent field defaults to `{}`
- Edit form reads `entry.definitionEnv` — env no longer erased on
save-then-edit cycle
### Unified descriptor (Phase A / Thufir F4)
- `EffectiveHarnessDescriptor { command, args, env }` in `readiness.rs`
- `resolve_effective_harness_descriptor()` — single resolver used by
spawn, spawn_hash, summary, get_agent_models (both saved and unsaved),
and readiness
- No competing arg-resolution forms
### Other fixes
- B-5: stop freezing `runtime.defaultArgs` into `record.agent_args` on
normal create paths
- B-7: readiness exec-check — `MissingBinary` variant for custom
commands not found on PATH
- B-8: onboarding transition — `setTimeout(0)` removed, parent-owned
route intent via `navigateAfterComplete` prop
- C-9: collector-discriminating sweep tests with injectable filters
- C-10: `HarnessManagementCard` uses `harnessGalleryLogic` helpers
(killed duplicate filter/sort)
- D-11: `BUILTIN_IDS` derived from `PRESET_HARNESSES` (no
hand-maintained copy)
- D-12: `mobile/pubspec.lock` churn reverted
- D-13: false ownership fast-path comment fixed
- D-14: URL scheme validation for `installInstructionsUrl`
- D-15: OpenClaw Gateway env-locus README line
### Tests added
**B-4 persistence (6 tests):**
`save_to_dir_create_writes_file_and_loads_back`,
`save_to_dir_same_id_edit_replaces_content`,
`save_to_dir_backup_is_cleaned_up_after_same_id_edit`,
`save_to_dir_rename_removes_old_file_and_creates_new`,
`save_to_dir_rename_nonexistent_old_id_is_non_fatal`,
`save_to_dir_roundtrip_with_env_preserves_values`
**B-3 env validation (6 tests):**
`validate_rejects_malformed_key_with_equals_sign`,
`validate_rejects_reserved_key_buzz_managed_agent`,
`validate_rejects_reserved_key_case_insensitive`,
`validate_rejects_nul_byte_in_value`,
`validate_rejects_value_over_per_value_size_limit`,
`validate_accepts_well_formed_env`
**B-2 API boundary (4 TS tests in tauri.test.mjs):**
`fromRawAcpRuntimeCatalogEntry maps definition_env to definitionEnv`,
`defaults definitionEnv to {} when absent`, `preserves source preset`,
`env round-trips through edit payload shape`
## Preset catalog
| ID | Label | Command |
|----|-------|---------|
| `cursor` | Cursor | `cursor-agent acp` |
| `omp` | Oh My Pi | `omp acp` |
| `grok` | Grok Build | `grok agent --always-approve stdio` |
| `opencode` | OpenCode | `opencode acp` |
| `kimi` | Kimi Code | `kimi acp` |
| `amp` | Amp | `amp-acp` |
| `hermes` | Hermes Agent | `hermes-acp` |
| `openclaw` | OpenClaw | `openclaw acp` |
## Review-fix pass (2026-07-26, Eva)
Fixes from the three-way review (Wren / Dawn / Eva) in the
buzz-generic-acp-harnesses thread, pushed as new commits (no rewrite):
1. **installHint edit round-trip** — form seeding extracted to
`formValuesFromCatalogEntry` (single source of truth), input rendered,
full-definition lossless round-trip regression.
2. **Dangling-delete coherence** — delete allowed; confirm counts
referencing agents (direct pin + persona-inherited); summary rows render
`harness (deleted): <id>`; spawn errors become actionable sentences
(`user_facing_harness_error`); composed delete→summary→start test.
3. **Comma-in-args** — rejected at `validate_harness_definition` (shared
by save AND disk load), mirrored inline in the form.
4. **Registry publish race** — collision/dup filtering moved into
`load_custom_harnesses` (both loaders inherit shadowing rules);
discovery publishes by re-reading the dir under `persist_mutex` (lock
scoped to publish only); deterministic interleaving regressions for
save-during-discovery and delete-during-discovery.
5. **Mechanical** — discarded `belongs_to_us` sweep arg deleted,
`load_global_agent_config` hoisted out of the per-record summary loop,
duplicated doc paragraph + stray SAFETY comment removed.
6. **PGID test de-flaked** — leader kept alive through the assertion.
Known follow-up (filed in review, not blocking): file-size split-outs
queued in `check-file-sizes.mjs` entries.
## Gate table — head `bf53f1d60`
| Gate | Result |
|------|--------|
| `cargo test --lib` (desktop/src-tauri) | **1701 passed**, 0 failed, 14
ignored |
| desktop JS suite (`pnpm test`) | **3605 passed**, 0 failed |
| `tsc --noEmit` | clean |
| `biome check` + file-size/px/pubkey checks | clean |
| `cargo clippy --lib -- -D warnings` | clean |
| `cargo fmt --check` | clean |
PR head: `bf53f1d60e3cbd07392e1287b83bb37ba90d0d33` — includes merge of
origin/main (`c2a4ee711`, conflicts in agent_models composed with
#2890's live Databricks discovery)
---------
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Co-authored-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: Dawn (sprout agent) <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
|
||
|
|
16d4ec335e |
feat(desktop): use collective mesh routing for Auto (#2825)
Uses MeshLLM built-in `mesh` collective intelligence / Mixture of Agents when Buzz Auto sees two or more distinct physical models. With zero or one model, Auto remains ordinary `auto`. This is an alternative way to improve tool responses, accuracy, and resistance to hallucination when a high-latency distributed mesh contains diverse models. Models and members may come and go: collective routing enables only after stable capacity, drops on confirmed contraction, and can recover later. Mesh-specific failures retry once through ordinary Auto. This update also pins MeshLLM to a v0.73.1-compatible backport of [MeshLLM #1074](https://github.com/Mesh-LLM/mesh-llm/pull/1074), so client-only Buzz nodes cannot enter model election or download a remote provider model. Buzz preserves the selected local sharing model and switches an existing client to sharing across a controlled app restart, retaining one runtime and one `:9337` / `:3131` pair per machine. Validation: - Full local `just ci` passes on the cleaned branch. - MeshLLM host-runtime suite: 1,568 passed, 0 failed; strict Clippy passes. - Buzz desktop Tauri suite with `mesh-llm`: 1,721 passed, 0 failed; strict feature Clippy passes. - Playwright covers client-to-share using the saved local model and no destructive stop. - Packaged two-machine testing proved single-model routing, dual-model collective routing, tool-markup fallback, and runtime reuse. - Packaged client-only recheck routed a real Mini Buzz turn through M5 while Mini stayed `is_client=true`, `is_host=false`, hosted no models, and created no Gemma cache. Builds on the recovery work merged in #2823; this PR does not duplicate it. --------- Signed-off-by: Michael Neale <michael.neale@gmail.com> Signed-off-by: Tyler Longwell <tlongwell@block.xyz> Co-authored-by: Michael Neale <michael.neale@gmail.com> Co-authored-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Tyler Longwell <tlongwell@block.xyz> |
||
|
|
aee6314484 |
fix(desktop): strip legacy baked team instructions from stored prompts (#3035)
Agents in a team receive two `Team Instructions` blocks per turn, and
the observer feed renders two Team Instructions cards for them.
There are two producers. `with_team()` in `crates/buzz-acp/src/pool.rs`
appends the LIVE `[Team Instructions]` block from the runtime
`TeamRecord` — that one is correct. The second is baked into the stored
`system_prompt` itself: records written before the runtime framing
landed were composed by the now-removed `compose_prompt()` in
`buzz-persona`, which appended `"\n\n---\n# Team Instructions\n"` plus a
frozen copy of the team instructions. So an affected agent is fed a
stale roster ahead of the current one, and the transcript parser —
correctly — reports both.
Fixing this in `parseSystemPromptSections` would hide the symptom while
the agent kept receiving the stale bytes, so the suffix is removed at
rest by a boot migration.
`strip_baked_team_instructions` splits each stored `system_prompt` at
the LAST occurrence of the exact delimiter and keeps the text before it.
Last-occurrence matches the parser's own `lastIndexOf` guard: a persona
body may quote a delimiter-shaped passage, and only the final one is the
producer boundary. The match is byte-exact — a bare `---`, a `# Team
Instructions` heading at a different position, or a single preceding
newline are author content and are left alone. It applies to every
record regardless of `team_id` / `persona_id` / `pubkey`: the key-less
definition records carry the suffix exactly as the instances minted from
them do. A prompt that was nothing but the suffix becomes `None`, not
`Some("")`, matching the absent-prompt convention in
`AgentDefinition::into_agent_record`.
Stripping a definition's prompt changes its `persona_content_hash`,
which is the drift basis behind the Agents-menu "out of date" badge.
Left alone, every linked instance would light up stale for a change the
user never made. The migration therefore advances the pin of instances
whose `persona_source_version` still equals the definition's PRE-strip
hash — the same conditional `refresh_builtin_agent_avatars` already
uses. An instance that had genuinely drifted keeps its stale pin, and
its badge.
The migration runs after `fold_personas_into_agent_store` so definitions
lifted out of the legacy `personas.json` are cleaned in the same boot,
and before `backfill_standalone_agents` so a manufactured definition
never snapshots a suffix about to be removed. It writes only when at
least one record changed, so a second boot is a true no-op, and takes a
create-if-absent backup at
`managed-agents.json.pre-team-suffix-strip.bak` following the
`pre-backfill.bak` contract — a re-run after a partial failure cannot
replace the pristine backup with a half-migrated snapshot. An
unparseable store errors without writing and without taking a backup,
leaving the file for manual recovery.
Pass 5's legacy branch in `agentSessionTranscriptHelpers.ts` is
deliberately untouched: un-migrated installs and snapshot imports still
need it.
---------
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
|
||
|
|
871a3b3772 |
Refine mobile community switching and discovery (#2967)
## Summary - Redesign community switching with relay-provided avatars, selected-state checks, edit-to-remove controls, and confirmation. - Bring desktop-inspired pairing onboarding to mobile with QR scanning as the primary action, an expandable pairing-code flow, and a tappable flapping bee. - Polish Search and Activity headers, filter chips, typography, keyboard stability, and Android adaptive-icon sizing. ## Validation - `just mobile-check` - `just mobile-test` — 661 passed, 1 skipped - Pixel 10 snapshot reviewmobile-v0.5.0-rc.2 |
||
|
|
5d8ede446f |
feat(agents): lower default agent parallelism from 24 to 10 (#3038)
## What
One-line default change: `DEFAULT_AGENT_PARALLELISM` 24 → 10
(`desktop/src-tauri/src/managed_agents/types.rs`), requested by Tyler in
[buzz-generic-acp-harnesses](buzz://message?channel=d6d84fdc-47fe-4e41-acf5-a08a4a013e6b&id=a047ead3a34ba804c376bf79f29e355d304162a88c7b2a7121e092547c572022).
## Why
Each unit of parallelism is a **full agent subprocess** per agent ×
community pair, spawned eagerly and serially at create/start before the
harness connects to the relay:
- At 24, a desktop with a few dozen agent×community pairs carries >1,000
potential idle subprocesses.
- Slow-starting harnesses (OpenClaw measured at 4–10s per worker) take
minutes to create, and messages sent during that window can be
permanently missed (the startup watermark is captured only after eager
pool init).
- Parallelism is per-channel concurrency — a channel never uses more
than one worker — so 10 still covers concurrent-channel fan-out for
typical agents.
Context: verified RCA + live 1-worker/3-mention experiment in the same
thread. Demand-driven pool growth (seed 1, grow on contention up to the
cap) is agreed as a follow-up; this is the interim risk reduction.
## Scope / blast radius
- Existing agent records keep their persisted `parallelism` value — only
new records and unset defaults change.
- Per-agent override unchanged (1..=32 via agent editor /
`BUZZ_ACP_AGENTS`).
- Readers of the constant (`team_snapshot`, `personas/snapshot/import`,
`commands/agents` mint path) all take the new default transitively; no
other code pins 24.
- `activeAgentTurnsStore.test.mjs` comments updated so the 24-turn
eviction case is framed against the harness cap (32) instead of the
default — coverage unchanged, no assertion touched.
## Verification
At
|
||
|
|
1a56b7cc9e |
feat(mobile): add worktree-aware debug identities (#2858)
**Category:** improvement **User Impact:** Developers can identify which worktree produced a mobile debug app, keep a bounded set of worktree builds installed side by side, and preserve each worktree app's login and local state while switching branches. **Problem:** Mobile debug builds from every checkout currently appear as the same “Buzz” app and share one application identity, so the running source is ambiguous and one worktree build replaces another. A branch-keyed identity would avoid replacement but create stale installs and fresh app state on every branch switch. **Solution:** Give each linked worktree a stable Debug-only application identity derived from its sanitized directory name. Show the sanitized branch name (or short commit SHA when detached) in the display label, persist generated native overrides for direct IDE builds, and leave Release/Profile identities unchanged. Worktree defaults remain lower precedence than a developer's iOS `AppOverrides.xcconfig`. `just mobile-clean` provides a safe cleanup path for suffixed worktree installs while preserving production Buzz. <details> <summary>File changes</summary> **.github/workflows/ci.yml** Runs the expanded worktree override contract when relevant mobile or native configuration changes. **AGENTS.md** Documents worktree-aware mobile development and cleanup for contributors and agents. **Justfile** Generates overrides before mobile development and Android debug builds, and exposes `just mobile-clean`. **mobile/README.md** Explains stable per-worktree identities, branch/SHA labels, direct IDE usage, cleanup, and Release/Profile guarantees. **mobile/android/.gitignore** Ignores generated worktree properties. **mobile/android/app/build.gradle.kts** Loads and validates generated properties, then applies the application ID suffix and display label to Android Debug only. **mobile/android/app/src/main/AndroidManifest.xml** Resolves the Android app label through an overridable string resource. **mobile/ios/.gitignore** Ignores generated iOS worktree settings. **mobile/ios/Flutter/Debug.xcconfig** Loads generated worktree defaults before developer `AppOverrides`, so personal signing overrides retain precedence. **mobile/ios/Flutter/Release.xcconfig** Pins the production display name and bundle identifier for Release/Profile builds. **mobile/ios/Runner/Info.plist** Resolves the visible iOS app name from build settings. **scripts/mobile-worktree-overrides.sh** Detects linked worktrees, derives a stable directory-keyed identity, sanitizes branch/SHA display context, writes native Debug overrides, and removes stale overrides in the main checkout. **scripts/mobile-worktree-clean.sh** Lists or removes suffixed Buzz worktree installs from booted iOS simulators and connected Android emulators without matching production IDs; supports `--dry-run`. **scripts/test-mobile-worktree-overrides.sh** Covers worktree detection, branch-switch identity stability, detached HEAD fallback, special-character sanitization, iOS override precedence, brace-aware Release/Profile purity, cleanup safety, ignores, and command integration. </details> ## Reproduction steps 1. From a linked worktree, activate the repository toolchain and run `just mobile-dev`. 2. Inspect the running app: its label should be `Buzz (<sanitized-branch>)`, while its application ID suffix is derived from the worktree directory. 3. Switch branches in the same worktree, rerun the override script, and confirm the application ID remains stable while the display label updates. In detached HEAD, confirm the label uses a short SHA. 4. Build Debug from a second worktree and confirm both apps remain installed side by side with independent state. 5. Build from Xcode after setting `AppOverrides.xcconfig` and confirm developer overrides still win over generated worktree defaults. 6. Run `just mobile-clean --dry-run`, then `just mobile-clean`, and confirm suffixed worktree installs are targeted while the production app is preserved. 7. Build Release/Profile and confirm the production name and application identity remain unchanged. 8. Run `scripts/test-mobile-worktree-overrides.sh`, `just mobile-check`, `just mobile-test`, and `just mobile-build-android`. ## Screenshots / demos | iOS — labeled app switcher | iOS — side-by-side installs | | --- | --- | | <img width="360" alt="Buzz worktree label in the iOS app switcher" src="https://github.com/user-attachments/assets/4bcae067-7ce5-4333-bb11-2803c4107663" /> | <img width="360" alt="Buzz production and worktree debug apps installed side by side on iOS" src="https://github.com/user-attachments/assets/08a107b5-fdf2-463a-8a4c-81d41d7bf5e7" /> | | Android — side-by-side installs | Android — labeled app switcher | | --- | --- | | <img width="360" alt="Buzz production and worktree debug apps installed side by side on Android" src="https://github.com/user-attachments/assets/4f5841a1-adae-42da-ae84-47c09ec85fb9" /> | <img width="360" alt="Buzz worktree label in the Android app switcher" src="https://github.com/user-attachments/assets/0546ff51-efcc-4cb6-a4bd-2a3af26cd60f" /> | --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com> Co-authored-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz> |
||
|
|
e6c90bb7c4 |
Polish community rail and mobile pairing (#2972)
## Summary - align the multi-community rail with the content surface and balance its visible 10px side gutters - center Mobile pairing, start sessions on demand, and keep retry states inside the QR area - reveal the QR code and copy action with 250ms motion and use the standard loading spinner The rail was centered within its own box, but the adjacent sidebar added another 11px to the visible right gap. Mobile pairing also started before user intent, which could leave an idle session waiting for EOSE. ## Validation - `pnpm -C desktop build:e2e` - `pnpm -C desktop test` — 3,516 passed - `pnpm -C desktop exec playwright test tests/e2e/community-rail.spec.ts --project=smoke` — 19 passed - `pnpm -C desktop exec playwright test tests/e2e/mobile-pairing-qr.spec.ts --project=smoke` — 1 passed `pnpm -C desktop check` is currently blocked by the existing `src-tauri/src/managed_agents/runtime.rs` file-size baseline (2,220 lines; limit 2,216). |
||
|
|
a31fc4d2f3 |
fix(desktop): remove bundled libsystemd from AppImage (#2353)
## Summary - AppImage bundles an older `libsystemd.so.0` that shadows the system copy after `libmount` is already removed - on systemd ≥ 251 (Arch, Fedora 41+, etc.) launch fails with `LIBSYSTEMD_251` not found - add `libsystemd.so*` to the existing removal list in `fix-appimage.sh` Closes #2335 ## Test plan - [ ] rebuild / repack an AppImage with the updated script - [ ] launch on a distro with systemd ≥ 251 without `LD_PRELOAD` workaround Made with [Cursor](https://cursor.com) Signed-off-by: Taksh <takshkothari09@gmail.com> |
||
|
|
dc1646fcb9 |
docs: document required DCO sign-off and add commit-msg sign-off hook (#2993)
`DCO Check` is a required status check on this repo and the top failing
check on open contributor PRs, but nothing documented it and nothing
surfaced it locally — a missing `Signed-off-by` trailer only showed up
as a red check after the PR was already open.
## `lefthook.yml`
New `commit-msg` hook that appends the `Signed-off-by` trailer:
```yaml
commit-msg:
commands:
signoff:
run: 'git interpret-trailers --if-exists doNothing --trailer "Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed ''s/ [0-9]* [+-][0-9]*$//'')" --in-place {1}'
```
`GIT_COMMITTER_IDENT` is the identity that performed the commit, which
is what a DCO sign-off certifies and what native `git commit -s` uses.
Committing someone else's work with `--author` or `git commit -C`
therefore signs off as you, not as the original author.
`--if-exists doNothing` makes it idempotent: `git commit -s` still
yields exactly one trailer, and an existing sign-off from a different
signer is preserved rather than supplemented. An empty commit message
still aborts — the hook does not turn one into a commit body containing
only a trailer.
Git runs `commit-msg` for `git commit` and `git merge` only. Other flows
bypass it and need their own sign-off flag — `git rebase --signoff`,
`git cherry-pick -s`. Note `-s` is `--strategy` on `git rebase`, so only
the long flag works there. The header comment and both docs state the
scope rather than promising blanket coverage. Installed by `just hooks`;
`commit-msg` carries no `glob` because it rewrites the message, not
files.
## `CONTRIBUTING.md`
`Before You Open a PR` gains a paragraph on sign-off: commit with `git
commit -s`, what the trailer certifies, that the required `DCO Check`
blocks merge without it, `git rebase --signoff main` to repair
already-pushed commits, and what the hook does and does not cover.
`CI Gate` gains one sentence pointing at `just fix-all` for
formatting-only failures.
## `AGENTS.md`
`Quality Gates` gains the same requirement framed for agents, including
the sequencer caveat and the reminder to include `-s` in
programmatically built commit commands.
## Related issue
none found
---------
Signed-off-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
|
||
|
|
8c0e8cb165 |
fix(desktop): make agent definition authoritative for model/provider/prompt (#1968)
## Summary
Introduces a single effective-config resolver that makes agent
definitions authoritative for model, provider, system prompt, and
relay-mesh routing on linked instances. Stale materialized record bytes
are never consulted at spawn, deploy, readiness, hash, card summary, or
mesh preflight.
**Resolution semantics (field-specific):**
- **model/provider (linked):** definition → global. `None` = inherit
global default. Record value never consulted.
- **model/provider (definition-less):** instance → global.
- **system_prompt (linked):** strictly from definition; blank = no
prompt. No global tier for prompt.
- **system_prompt (definition-less):** from the instance.
- **relay-mesh preflight (both):** driven by the same
`resolve_effective_config` resolution spawn's mesh env consults. For a
linked instance the record's own `provider`/`model`/`relay_mesh` bytes
are never consulted; for a definition-less instance with no provider of
its own, the legacy marker and env preset are the last fallback (see
below).
- **Orphaned (linked record, definition missing):** spawn, deploy, and
mesh preflight blocked with actionable user-facing error.
**Changes:**
- New `effective_config` resolver module with `ConfigSource` metadata
(`definition`, `global`, `instance_legacy`)
- All consumers routed through the single resolver: local spawn, deploy,
readiness, spawn hash, card summary, relay-mesh preflight (interactive
start and restore-on-launch)
- `apply_persona_snapshot` no longer preserves stale record
model/provider when definition is blank
- Backend `update_managed_agent` blocks model/provider/prompt writes for
linked records
- Frontend omits model/provider/systemPrompt submission for linked
instances; system prompt override hidden
- `model_source` field added to `ManagedAgentSummary` so card labels
distinguish inherited (`Default model (X)`) from explicit
- Spawn hash now digests resolved model/provider (not raw record fields)
so global default changes trip the restart badge even for runtimes
without `model_env_var`
- Orphan spawn/deploy/mesh-preflight blocked with jargon-free error
("This agent's configuration is missing — it may still be syncing or was
deleted on another device")
- `EffectiveAgentConfig::relay_mesh_model_id()` and
`resolve_effective_relay_mesh_model_id()` added; both mesh preflights
(`start_local_agent_with_preflight`, `restore_managed_agents_on_launch`)
call this instead of the deleted
`relay_mesh_config`/`relay_mesh_model_id` record-byte sniffs
- Legacy relay-mesh records keep their mesh routing. Two shipped
generations predate `provider: "relay-mesh"` and are never rewritten on
load: the typed `relay_mesh` marker (added when `ManagedAgentRecord` had
no `provider` field), and before it the mesh preset written directly
into `env_vars`. `resolve_definition_less` falls back to the marker,
then to the env preset, so these records still resolve to mesh instead
of silently misrouting to an unrelated provider while their stale env
bytes reach the child. The fallback is skipped when the record carries
an explicit `provider` — that states current intent, including a switch
away from mesh — and `resolve_linked` has no legacy fallback at all
- The env discriminator accepts both spellings of the two sentinels
renamed in the Jun-11 window without a record migration: the provider
env key (`BUZZ_AGENT_PROVIDER`, previously `SPROUT_AGENT_PROVIDER`) and
the api-key value (`buzz-mesh-local`, previously `sprout-mesh-local`).
Each is independent, since a record can straddle the window; the current
provider-key spelling wins when both are present
- Dead `persona_field_with_record_fallback` and wrapper
`persona_snapshot_with_agent_config_fallback` deleted; callers use
`persona_snapshot` directly
- New resolver/deploy/hash/write-guard/mesh-preflight tests, including
switch-away and global-inheritance regressions for both mesh preflight
call sites, per-class legacy-mesh resolution (typed marker and env
preset, in every rename-window spelling combination), and the paired
assertions that a linked instance's legacy mesh bytes stay inert
---------
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
|
||
|
|
8e67cf399d |
chore(desktop): delete dead persona catalog UI cluster (#2886)
## Summary - Deletes 6 orphaned files in `desktop/src/features/agents/ui/` (556 lines) that formed a closed cluster with zero imports from the reachable module graph — orphaned by the 1B dialog consolidation (`PersonaCatalogSurface`, `PersonaCatalogSection`, `PersonaCatalogDetailsSheet`, `PersonaCatalogSelectionBadge`, `PersonaIdentity`, `PersonaLibraryEntryPoints`). - Removes a stale `check-file-sizes.mjs` override entry for the no-longer-existent `PersonaDialog.tsx`. Verified dead two ways: import-graph reachability walk from all entry points puts all six outside the reachable set, and `tsc --noEmit` passes clean after deletion. Their `data-testid`s have zero references outside the cluster. `PersonaCatalogDialog.tsx` is alive (`AgentsView` imports it) and stays. Independent of #1968 — pure dead code removal, no behavioral change. |