Merge upstream/main into adrienlacombe/buzz (2026-08-18) - #47
Merged
Conversation
…e manifest (block#5597) ## Summary Centralizes model capability knowledge — thinking mode, supported effort levels, wire routes, and human-readable labels — into a single manifest, `scripts/model-capabilities.json`. Rust and TypeScript each get a small interpreter that reads the same manifest, replacing hand-maintained tables scattered across both languages that had already drifted apart. A capability change is now a data edit, not parallel edits to two code paths. Supersedes the codegen approach explored in block#3603. A cross-language contract keeps the two interpreters honest: `scripts/normative-corpus.json` is a golden snapshot generated from the Rust resolver (103 vectors covering all six capability axes) and replayed natively in TS. CI fails if either language disagrees with the corpus or the corpus drifts from the resolver. Regenerate with `just regen-model-corpus`. ## Behavior changes - **Effort dropdown for `openai-compat` providers** no longer offers `max`. The request path always clamped `max` to `xhigh` on the wire, so the UI stops offering a value that was silently rewritten. UI-only, wire-identical. - **Databricks v2 routing (wire-visible):** uncurated endpoint names carrying a bare Claude code-name segment (e.g. `goose-opus-5`) now route to the MLflow chat wire instead of Anthropic Messages — they lose Anthropic prompt caching but still succeed on a valid OpenAI-compatible wire. Curated `databricks-claude-*` records and any name starting with `claude` are unchanged. A handful of other uncurated/adversarial name shapes similarly fall back to MLflow chat instead of pattern-matched routes; every curated model resolves identically to before, all axes. - **Curated model labels on the real discovery path.** The Databricks API returns no display name, so discovery emits the raw endpoint id as the model `name` (`{id, name: id}`) on every path. `ModelEntry.name` is now curated at all four construction seams in `buzz-agent` — v2 discovery, v1 parse, the auth-empty default catalog, and the configured-model fallback — via a read-only `databricks_registry_label` lookup over the manifest's `databricks_v2` exact records; `id` stays the raw wire/config value. A known id renders its curated label (`databricks-gpt-5-5` → `GPT-5.5`), an unknown id passes through unchanged, and the default-catalog row reads `GPT-5.5 (default catalog)`. As a defense against older `buzz-agent` binaries and any harness that echoes ids, `resolveModelLabel` treats a discovered name equal to the trimmed id as absent and falls through to the registry tier; a genuinely distinct name (including the suffixed default-catalog label) still wins. ## Cleanup Deletes the duplicated capability tables and their tests: the `config.rs` gpt5 matchers, effort tables, and clamp logic; the legacy segment-based Databricks v2 route classifier in `llm.rs`; and the TS hand tables plus `effortTable.fixture.json`. All are replaced by manifest lookups through the shared resolver — no line of capability data exists in two places. --------- Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
## Summary - discover shared managed agents from authenticated relay directory records instead of treating channel membership as sufficient proof - publish and refresh access-policy changes immediately so running clients converge across machines without a restart or five-minute poll - route profile edits through the exact managed instance and stop/restart runtimes around access changes so unrelated edits cannot silently widen access - keep mention send-time revalidation and Block owner-only build enforcement fail closed - explain invalid custom provider/model configuration instead of leaving Save silently disabled ### Related issue Fixes block#3204 ### Known residuals - a brand-new remote agent's first policy record can wait for the bounded directory poll when no authenticated directory coordinate exists yet; send-time mention revalidation remains fail closed - a failed remote-provider policy redeploy is recorded but cannot undeploy the older provider instance until the provider protocol gains the destructor tracked by block#5570 ### Testing - full Desktop unit suite: 4,961 tests passed - focused profile editor Playwright workflow passed, including Customize access edits and prompt-only edits after tightening an instance - Desktop TypeScript, Biome formatting, file-size ratchet, Tauri checks, and pre-push suites passed - independently reviewed for authenticated directory trust, live subscription teardown, runtime revocation ordering, fail-open edit paths, and per-agent provider deployment serialization --------- Signed-off-by: Wes <wesbillman@users.noreply.github.com> Signed-off-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@buzz.block.builderlab.xyz> Co-authored-by: diegorumo <diegorumo@gmail.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz> Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@buzz.block.builderlab.xyz>
**Category:** improvement **User Impact:** Users can scan what each workflow does and trigger, edit, duplicate, enable, disable, or delete it directly from the library. **Problem:** The workflow list buried common actions and did not expose each automation's trigger-to-action shape at a glance. **Solution:** Add a responsive workflow library with a persistent create tile, compact trigger/action diagrams, prominent workflow titles with supporting descriptions, and shared card actions while preserving existing detail, editor, and run-history entry points. Card toggles refresh both list and open-detail caches so status and definition stay consistent. <details> <summary>File changes</summary> **desktop/src/features/workflows/ui/WorkflowActionsMenu.tsx** Adds a shared card menu for trigger, edit, duplicate, enable/disable, and delete actions. **desktop/src/features/workflows/ui/WorkflowCard.tsx** Reworks cards around the prototype's visual hierarchy: color-coded trigger, action flow, sentence-case eyebrow, prominent title, supporting description, status, channel, and update date without a footer clock icon. **desktop/src/features/workflows/ui/WorkflowsView.tsx** Adds the responsive grid, create tile, mutation wiring, and list/detail cache invalidation. Container breakpoints keep cards two-across at medium widths and three-across in the 1280px desktop layout. **desktop/src/features/workflows/ui/workflowDefinition.ts** Adds immutable enabled-state updates plus narrow trigger and first-action readers used only to select card icons. **desktop/src/features/workflows/ui/workflowDefinition.test.mjs** Covers neutral icon selection, enabled-state immutability, and status presentation. **desktop/tests/e2e/workflows.spec.ts** Covers the create tile, title/description hierarchy, selected-card enable/disable consistency, and deterministic narrow/medium/wide captures while retaining existing action coverage. </details> ## Reproduction steps 1. Open **Workflows** and confirm the create tile stays first as cards flow from one to three columns with available width. 2. Confirm each card shows a sentence-case trigger eyebrow, prominent workflow title, supporting description when present, status, channel, and update date without a clock icon. 3. Open a card's overflow menu and trigger, edit, duplicate, enable/disable, or delete the workflow. 4. Leave the detail panel open while toggling and confirm its badge and JSON definition update with the card. ## Screenshots Real built E2E UI with representative workflow data at three viewport sizes. ### Narrow — 800 × 720  ### Medium — 1024 × 720  ### Wide — 1280 × 720  ### Card actions  --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
## Why Buzz currently appends its managed prompt to Goose's native prompt, so managed agents receive both instruction sets instead of the intended Buzz-only system prompt. ## What - Send Goose's custom session system-prompt request with `mode: "set"` - Lock the replacement contract in the ACP request test ## Risk Assessment Low — the change is limited to Goose session setup; adapters that do not implement Goose's custom method keep the existing method-not-found fallback behavior. ## References Goose v1.46.0 routes `set` to `override_system_prompt`, and its prompt builder selects that override instead of rendering the native `system.md`: [ACP handler](https://github.com/aaif-goose/goose/blob/98c11ce2ee7b9b302978aa64b1eab7d0895607c7/crates/goose/src/acp/server/manage_sessions.rs#L57-L93), [prompt builder](https://github.com/aaif-goose/goose/blob/98c11ce2ee7b9b302978aa64b1eab7d0895607c7/crates/goose/src/agents/prompt_manager.rs#L153-L191). Validated end to end against the official Goose v1.46.0 binary with a local OpenAI-compatible capture server: the provider request contained the exact Buzz replacement prompt and did not contain Goose's native base-prompt marker. --- **Update Aug 15, 13:17 CDT:** Added the [Terra-high prompt-ablation comparison](https://github.com/squareup/buzz-benchmarks/blob/4492f76349ccb638219f7d070735a4d2b679bc26/data/prompt-ablation/20260815-terra-high/comparison.md). The Goose conditions used GPT 5.6 Terra at high effort on the same 11 Terminal-Bench 2.1 tasks, with two attempts per task and concurrency four. The matched `append-full` and `set-full` runs used the same persona and included the same Buzz platform prompt; Active-h is the primary measure because it excludes Buzz lifecycle overhead. | Goose condition | Pass | Active-h | Median active | Agent-h | Wall-h | Tool calls | |---|---:|---:|---:|---:|---:|---:| | Native prompt + Buzz prompt (`append-full`) | 21/22 | 0.3042 | 0.85 min | 0.3974 | 0.1496 | 234 | | Native prompt + persona only (`append-persona-only`) | 22/22 | 0.3050 | 0.75 min | 0.3990 | 0.1498 | 204 | | Buzz prompt replaces native prompt (`set-full`) | 22/22 | 0.3340 | 0.87 min | 0.4296 | 0.1551 | 275 | Replacing instead of appending produced one additional passing attempt, but it was not an efficiency improvement in this small sample: versus `append-full`, `set-full` increased Active-h by 9.8%, median active by 2.0%, Agent-h by 8.1%, Wall-h by 3.7%, and tool calls by 17.5%. It was faster on only two of eleven per-task active-time medians (`distribution-search` and `prove-plus-comm`). With two attempts per task, these are directional results rather than confidence intervals; they support this change as an instruction-isolation/correctness fix, not a performance optimization, and argue against Goose's appended native prompt being the main source of active-time cost. Generated with Codex Signed-off-by: Atish Patel <atishpatel2012@gmail.com> Co-authored-by: Codex <noreply@openai.com>
…hor (block#6129) ## Problem Scheduled workflow `send_message` actions fire and land in the channel with correct `p` tags for the mentioned agents — but the agents never wake. The wake-up is silently dropped. **Root cause:** workflow messages are signed by the **relay keypair** (`workflow_sink.rs` signs with `state.relay_keypair`), so `event.pubkey` is the relay's pubkey, not the workflow owner. In `buzz-acp`, the inbound author gate (`author_allowed`) runs **before** the `p`-tag mention check. Under the default `respond_to = owner-only`, the relay pubkey is neither the owner nor a sibling, so every workflow wake-up dies at the gate with a debug-level `"inbound author gate — dropping event"`. The relay-side comment even says the mention `p` tags exist *"so mentioned agents are woken (wake is p-tag gated)"* — but wake is also author-gated, and that path was missed. ## Fix Gate relay-signed workflow messages on their **attributed author** — the pubkey that created the workflow — instead of the relay pubkey: - **Relay:** `workflow_sink.rs` now emits an explicit `buzz:workflow-owner` tag carrying `workflow.owner_pubkey` (the workflow creator, which the executor already passes as `author_pubkey` and whose channel access the relay verifies before emitting). Ownership is never inferred from `p`-tag order; mention `p` tags play no role in attribution. - **Harness:** at startup, `buzz-acp` fetches the relay's NIP-11 `self` pubkey (new `RestClient::fetch_relay_self`, public `/info` endpoint). Best-effort: fetch failure just logs a warning and preserves pre-fix behavior. - **Gate:** an event that is (a) authored by the relay `self` key, (b) tagged `buzz:workflow`, and (c) carries a well-formed `buzz:workflow-owner` pubkey is gated on that owner, through the exact same owner/sibling/allowlist policy as a direct author. ## Security notes (all fail closed) - No NIP-11 `self` pubkey → no exemption. - `buzz:workflow` / `buzz:workflow-owner` tags on a non-relay-signed event → ignored (a member cannot forge the exemption; the relay verifies signatures on submission and only the relay holds its key). - Relay-signed event without the tags, or with a malformed owner value (not 64-hex) → plain author gate. - Who is @mentioned in the message has no bearing on whose authority is evaluated. - A workflow owned by a random channel member still cannot wake an owner-only agent — the owner's pubkey must pass the same policy. ## Testing - 7 unit tests (`workflow_attributed_author_tests`) covering attribution, fail-closed paths, p-tag independence, malformed owner values, and the forgery case. - Extended the PG-gated `workflow_send_message_p_tags_mentioned_member` integration test to assert the `buzz:workflow-owner` tag. - `cargo test -p buzz-acp`: 785 passed, 0 failed. `cargo test -p buzz-relay --lib workflow_sink`: 17 passed. Clippy + fmt clean. (9 pre-existing `buzz-relay` failures in unrelated `api::media`/`api::admin` tests fail identically on the base commit without this change.) Found while debugging scheduled automations in a Buzz review-pipeline channel: two cron workflows fired daily @mentions at agents that never responded, while direct human @mentions woke them instantly. --------- Signed-off-by: Luke Tornquist <tornquist@squareup.com> Co-authored-by: Fizz <3a9f8a30fbb462abec1e2977b2280a7ae50c7ff794433790be15bd48bfd52d0b@buzz.block.builderlab.xyz>
…or (block#5706) Agent profiles resolve through one shared selector (`pickProfileAgent`) at every entry point — the persona card, the profile panel, and library grouping. That selector ranked instances only by active/name, with no archive awareness, so a relay-archived instance early in file order could hijack the persona card and the profile panel. The persona card also recorded a durable pubkey target, which could strand the panel on an archived identity when the click landed during the archive-snapshot fail-open window. The profile panel's Runtime → Instances roster had the same blind spot: it rendered every persona instance raw, so archived instances appeared mixed in with live ones as if active. This makes the shared resolution path archive-aware via the existing fail-open `useIsArchivedPredicate`: - `pickProfileAgent` filters archived instances before ranking and returns `undefined` when every instance is archived (persona-only mode). - `buildUnifiedGroups` drops archived agents from the standalone `Custom agents` and `Unknown agents` buckets; matched persona groups keep their full list and rely on the selector's persona-only fallback. - `useCanonicalManagedAgentProfile` resolves through a pure `resolveCanonicalManagedAgent` helper that applies the target-provenance rules: a deliberately requested archived pubkey stays exact (so its archive controller can unarchive it, even when a live sibling exists), `preserveRequestedInstance` still pins a Runtime → Instances selection, and non-archived historical navigation keeps its canonicalization. - The persona card's main click records a persona target that re-resolves every render, so it self-corrects to a live sibling after hydration. Deliberate instance navigation and the runtime-error affordance keep their explicit-pubkey path. - The Runtime → Instances roster (`ProfileInstancesSection`) buckets instances off the same predicate via `bucketPersonaInstances`: live rows render as before, and archived rows move under a labeled `Archived` subsection. The instance count reflects both buckets, and archived rows keep their explicit-pubkey click so unarchive stays UI-reachable (the deliberate-navigation path above). The predicate is fail-open (treats every identity as live while the relay archive snapshot loads) and self-exempt, so a cold start never hides an identity and a user is never folded from their own client. While the snapshot is loading, every instance renders in the live list — nothing hidden, nothing labeled. --------- Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
## Summary - Rename the built-in Bumble agent to Pollen across desktop, onboarding, docs, and test fixtures. - Migrate existing stock definitions and instances in place while preserving customized fields and the stable persona coordinate. - Reserve the Pollen name by removing it from Fizz's generated-name pool. ## Validation - Pre-push desktop checks, typecheck, 4,791 frontend tests, Tauri clippy, and 2,432 native tests - Desktop E2E build --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Kenny Lopez <klopez4212@gmail.com> Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Removes the promise in `SECURITY.md` to publish a GitHub Security Advisory after every security fix is released. The disclosure policy continues to state that Buzz follows coordinated disclosure and credits reporters unless they request anonymity. Checked with `git diff --check`. Signed-off-by: Jordan Mecom <jm@squareup.com>
…lock#5666) Fixes block#5665. `next_timestamp` in `crates/buzz-cli/src/commands/projects.rs` computed a replacement's `created_at` as `head.created_at + 1`. The relay's ingest path rejects events more than ±900s from server time (`MAX_TIMESTAMP_DRIFT_SECS` in `crates/buzz-relay/src/handlers/ingest.rs`), so: - `projects update` on any project whose head is older than 15 minutes fails with `relay error 400: invalid: event timestamp too far from server time` (live repro in block#5665); - inside the window, replacements are recorded at `head+1` — seconds-to-minutes in the past — so a concurrent wall-clock writer silently wins LWW and audit timestamps misstate when the write happened. ## Change `next_timestamp` now returns `max(now, head.created_at + 1)`: strictly after the observed head (preserving the dominate-the-head guarantee for skewed/future heads), never behind the wall clock. This mirrors the relay's own replacement-authoring pattern (`now.max(head+1)` in `side_effects.rs`). ## Testing - `cargo test -p buzz-cli --lib` — 344 passed; adds `next_timestamp_uses_wall_clock_when_head_is_stale`, and the existing far-future-head test still holds (`head+1` wins when head > now) - `cargo clippy -p buzz-cli --all-targets` / `cargo fmt --check` — clean - Live before/after on a self-hosted relay: vanilla CLI fails on a 2h-aged head; with this change the same update is accepted and the head lands at wall clock. Same failure family as block#2876 (`repos protect` vs the drift window) — that path is not touched here. --------- Signed-off-by: Ika Minami <ika@infiniteidol.com> Signed-off-by: Ravneet Arora <rarora@squareup.com> Co-authored-by: Ika Minami <ika@infiniteidol.com> Co-authored-by: Ravneet Arora <rarora@squareup.com>
block#5904) Two membership-propagation defects let an agent team silently lose members — both observed live on Will's store (Sietch Tabr), not hypothetical. **Stale `persona_ids` dropped on save.** Team records written before persona ids were namespaced hold bare slugs (`thufir`) instead of the namespaced id (`sietch-tabr:thufir`). Nothing rewrites them, and the interactive save path (`ensure_persona_ids_are_active`) *drops* any id it cannot resolve — so the next in-app save shrinks the team. This nuked four of five Sietch Tabr members. **`team_id` drifts from team membership.** Team instructions are injected at spawn by matching `record.team_id` (`spawn_snapshot::effective_team_instructions`), so an instance's binding must track its persona's membership. It drifts two ways: adding a persona to a team leaves the persona's already-running instances at `team_id: null` (a member in the roster but not in behavior — seen twice, Gurney and Hayt), and removing a persona while keeping its agents leaves the kept instance bound to a team that no longer lists it (still drawing that team's instructions at spawn). ## Fix A boot migration (`migration/team_membership.rs`) heals existing stores in one pass over `teams.json` + `managed-agents.json`: - **Rewrite stale ids.** A stale id is one no definition slug resolves. Its target is the definition whose `source_team_persona_slug` equals the bare slug, scoped to the team's source team (via `source_dir` for a directory-backed team, or the unique `source_team` among resolvable members for a detached one). Rewrite only when exactly one candidate matches; zero or many leave the id in place — strictly safer than the save path, which drops it. - **Repair `team_id`.** Backfill an instance whose persona is a team member but whose own binding is unset, and heal a stale binding whose team no longer lists the persona (re-point when exactly one *other* team claims it, otherwise unbind). Both directions gate on single-team evidence — a persona spanning several teams has none (JSON team order is not ownership), so it is left as-is and logged. A binding whose team still lists the persona is authoritative and never touched. Runs BEFORE `detach_directory_backed_teams` (so a not-yet-detached team can still be scoped by its `source_dir`) and before any UI save can drop an id. Rewrite-or-leave converges to a fixed point, so a second boot is a no-op; the store is backed up once before either write. The edit path (`commands/teams.rs`) propagates a membership change to live instances immediately, without waiting for the next boot, scoped to the delta between the pre-edit and post-edit rosters: - **Added personas** (on the team now, not before) backfill `team_id` on their unbound instances. An explicit add is legitimate binding evidence even for a persona shared across teams — unlike the order-blind boot case. - **Removed personas** (on the team before, not now) clear `team_id` on instances bound to *this* team (bindings to other teams are untouched), so a "keep agents" removal stops feeding a kept instance the old team's instructions. - **Delta-scoping keeps a metadata-only edit inert:** with no roster change, no instance is re-pointed — a shared unbound persona is never silently bound to whichever team was edited last. Propagation is best-effort after the authoritative `save_teams` (mirroring `retain_team_pending`): the team already exists on disk, and boot repair is the designed retry for a stale/unset binding, so a secondary `managed-agents.json` write failure no longer fails a command whose team write succeeded — which would otherwise let a UI retry mint a duplicate team. --------- Signed-off-by: Will Pfleger <pfleger.will@gmail.com> Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
## Summary - apply the inactive primary-navigation opacity treatment to every sidebar destination, including Pulse, Projects, and Workflows - remove the duplicated Inbox and Agents conditionals so future gated rows inherit the same hierarchy - add E2E coverage for all inactive rows and restoration to full opacity when selected ## Validation - `pnpm --dir desktop build:e2e` - `pnpm --dir desktop exec playwright test badge.spec.ts --grep "primary navigation rows share the same inactive emphasis" --project=smoke` - pre-push hook: desktop check, typecheck, and 4,984 unit tests Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Why Managed channel sessions already receive authoritative per-turn context. The old startup recovery checklist told every new session to scan the global feed ## What - Remove `Startup Recovery` with concise channel and heartbeat turn contracts. ## Risk Assessment Low. This changes prompt guidance and its test only; routing and runtime behavior are unchanged. Generated with Codex --------- Signed-off-by: Salman Mohammed <smohammed@squareup.com>
**Category:** fix **User Impact:** Workflow listings reliably include every accessible channel, including for users with more than 128 memberships and when connected to older relays. **Problem:** Multi-value `#h` filters could lose live delivery, apply channel scoping after SQL limits, mishandle partial authorization or revocation, and permit unbounded membership work. Desktop also submitted every channel in one request, exceeding the relay's new 128-value safety bound. **Solution:** Preserve NIP-01 OR semantics across relay query, count, and live-subscription paths while enforcing authorization and bounded explicit-channel work before database or Redis operations. Desktop keeps the older-relay-compatible one-channel-per-filter shape, sends filters in bounded batches, combines responses, and deduplicates signed events by event ID. <details> <summary>File changes</summary> **crates/buzz-db/src/event.rs** Distinguishes authorization channel scopes from explicit `#h` scopes in list and count SQL so requested channels are applied before limits without implicitly including global rows. **crates/buzz-relay/src/handlers/req.rs** Shares explicit-channel scope extraction and limits, preserves valid OR siblings when malformed branches cannot match, repairs request-local membership misses, and registers authorized live subscriptions per channel. **crates/buzz-relay/src/handlers/count.rs** Applies the same bounded explicit-channel authorization to COUNT and preserves channel scope when a multi-channel request narrows to one authorized channel. **crates/buzz-relay/src/api/bridge.rs** Brings HTTP query and count behavior in line with WebSocket semantics before SQL execution and rejects over-limit explicit-channel requests before membership I/O. **crates/buzz-relay/src/subscription.rs** Indexes multi-channel subscriptions by every authorized channel and shrinks, rather than destroys, their scope when one channel is revoked. **crates/buzz-relay/src/handlers/side_effects.rs** Releases only revoked channel topics and sends terminal closure only when no authorized channel remains. **crates/buzz-test-client/tests/e2e_relay.rs** Adds ignored relay integration coverage for multi-channel delivery and valid historical/live behavior with malformed or empty OR siblings. **desktop/src-tauri/src/commands/workflows.rs** Builds one single-channel filter per membership, submits at most 128 per relay request, combines batches, and deduplicates by immutable signed event ID. **desktop/src-tauri/src/commands/workflows_tests.rs** Covers filter compatibility, malformed input, 129-channel batching, and cross-batch event-ID deduplication. </details> ## Reproduction steps 1. Join multiple channels containing workflows, open **Workflows**, and confirm workflows from every accessible channel appear. 2. Repeat with more than 128 memberships and confirm the listing remains complete rather than failing the relay request. 3. Send a multi-value `#h` query/count and confirm only requested authorized channels affect SQL limits and counts. 4. Subscribe to channels A and B, revoke A, and confirm B continues delivering live events. 5. Subscribe with a valid channel branch plus a malformed or empty `#h` sibling and confirm valid history, EOSE, and post-EOSE live delivery still occur. ## Validation At pushed head `c419a923f05e483ab26c006a0b3a80cfb3c73844`: - Relay request tests: 53 passed. - Desktop full Rust unit suite: 2,468 passed, 17 ignored. - Relay E2E target compiled with `--no-run`. - Strict relay clippy passed. - Desktop Tauri clippy/check passed. - Pre-push Rust tests and Desktop Tauri checks passed. - Rust formatting and `git diff --check` passed. --------- Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
## Summary - preserve selected managed-agent `p` tags when fresh managed-directory evidence succeeds but relay discovery or owner-profile lookup fails - keep relay-only agents fail-closed unless fresh relay evidence and any required owner proof are available - cover selective admission with focused unit tests and a signed-event Playwright regression ## Testing - `node --import ./desktop/test-loader.mjs --experimental-strip-types --test desktop/src/features/messages/lib/agentMentionRevalidation.test.mjs` (7 passed) - focused Playwright regression plus adjacent relay-revocation case (2 passed) - pre-commit desktop Biome/file-size hook - pre-push desktop check, TypeScript typecheck, and full desktop unit suite (4,987 passed) Fixes block#6147 Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Buzz Desktop release v0.5.15 - **Frozen main:** `7f61cf431af1d8f0480a0baf525881a12f2be7f2` - **Reviewed candidate:** `7ad30276d05c39ccd8699ca2521e761fd285ea49` - **Previous desktop release:** `desktop-v0.5.14` - **Proposed immutable tag:** `desktop-v0.5.15` This PR may be **squash merged** after the Desktop Release Candidate check and all protected-branch checks pass. Merging authorizes publication of the exact reviewed candidate; later or unrelated changes on `main` cannot alter it. The checked-in changelog accounts for every non-merge commit in the release range. The Desktop tag points to the reviewed candidate commit, not the later squash commit. Publication remains bound to that immutable candidate tag. Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Release Automation <release-automation@users.noreply.github.com>
## Summary - retain explicit regression coverage for the exact 128-channel relay request limit - cover the 129-channel split into 128 + 1 filters The workflow-listing implementation originally carried by this PR landed through block#6009. This branch is now rebased onto current `main`, so the remaining diff is only the boundary test that block#6009 did not include. Fixes block#6116 ## Test plan - `cargo test --manifest-path desktop/src-tauri/Cargo.toml workflow_queries_respect_relay_explicit_channel_limit` - pre-push hook: Desktop checks, Desktop tests, Desktop Tauri checks, and path-scoped Rust tests Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com> # Conflicts: # desktop/src-tauri/tauri.conf.json # desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upstream range
3eab39538..f8692fa9b— 16 upstream commits (block/buzzmain).Merged with
git merge --no-ff, both parents preserved:Merge with a merge commit, not squash. A squash drops the second parent, leaves the merge base stale, and every later sync re-resolves the same conflicts from it (repaired by hand once already in
3ce7c8adc).What changed upstream
Model capabilities (block#5597) — the largest change. Model capabilities and labels now come from one manifest (
scripts/model-capabilities.json) with a golden normative corpus (scripts/normative-corpus.json) replayed as a cross-language drift guard from both Rust (buzz-agent/src/model_capabilities.rs,include_str!) and TS (modelCapabilitiesCorpus.test.mjs). Replaces the oldeffortTable.fixture.json. Adds ajust regen-model-corpusrecipe and a newcargo nextest run -p buzz-agent --libstep totest-unit.Relay / workflows
handlers/req.rs(+379/-97),subscription.rs(+279/-84),handlers/command_executor.rs(+263/-11),handlers/count.rs,api/bridge.rs,buzz-db/src/event.rs,buzz-core/src/filter.rsDesktop
migration/team_membership.rs)WorkflowActionsMenu.tsx)migration/pollen.rs)Agent harness — block#5964 replace Goose native system prompt, block#6161 remove Startup Recovery section from base prompt
Other — block#6173 release Buzz Desktop 0.5.15, block#5666 keep project replacement timestamps at or after wall clock (cli), block#6144 remove GitHub security advisory commitment
No changes under
migrations/,crates/buzz-core/src/kind.rs,crates/buzz-relay/src/handlers/ingest.rs,crates/buzz-db/src/migration.rs, ormobile/.Conflicts
2 files.
desktop/src-tauri/tauri.conf.jsonUpstream bumped
version0.5.14 → 0.5.15 on the line directly below the fork'sproductName/identifierrename. Resolved as the patch table prescribes: keptproductName: "BitcoinMarkets"andidentifier: "app.bitcoinmarkets.desktop", took upstream's version. Deep-link scheme (bitcoinmarkets) untouched.desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsxUpstream block#6163 moved the inactive-row dimming out of JSX and into CSS: it added a
sidebar-primary-menuclass to<SidebarMenu>and deleted the per-rowopacity-80conditionals on the Inbox and Agents icons/labels. The new rule inglobals/components.cssisThe fork restructures that same Inbox row so Inbox and Markets share one primary-menu row. The Agents hunk merged clean; the Inbox hunk conflicted.
Resolved as keep both: the fork's shared Inbox+Markets row structure and its
right-1badge offset are preserved, and upstream's two changes are applied on top of it — thesidebar-primary-menuclass is taken, and the JSXopacity-80conditionals on Inbox are dropped in favour of the CSS rule.Worth noting for review: because upstream's selector is descendant-based and applies to every inactive button in the menu, the fork's Markets button now picks up the same inactive dimming it never had before. That is upstream's stated intent — its comment says the treatment is on the menu specifically so "newly gated rows" cannot render at stronger emphasis than Inbox and Agents — so this reads as the fork's row falling into line, not as a regression. The extra
<div>wrappers in the fork's row do not break either selector; bothcomponents.cssand the existingtheme.cssprimary-menu rule are descendant selectors.Verification
cargo fmt --all --checkcargo fmt --manifest-path desktop/src-tauri/Cargo.toml --all --checkcargo clippy --workspace --all-targets -- -D warningscargo clippy --manifest-path desktop/src-tauri/Cargo.toml --all-targets -- -D warningscargo metadata --locked(root)cargo metadata --locked(desktop)scripts/test-release-ref-contract.shrelease ref contract passedscripts/test-mobile-worktree-overrides.shall mobile worktree identity contract checks passedjust test-unitcargo test --manifest-path desktop/src-tauri/Cargo.toml --libbiome check(desktop)check-file-sizes.mjscheck-px-text.mjscheck-pubkey-truncation.mjsrelease.ymlassemble-manifestgate integrityneeds.<job>.resultpnpm installtsc --noEmitThe two blocked gates
pnpm installfails this machine's supply-chain policy check for six@atomiqlabs/*lockfile entries, all404fromhttps://npm.pkg.github.com. The cause is local developer config, not the repo: a machine-level npmrc maps the@atomiqlabsscope to GitHub Packages, where those packages do not exist — they are on public npm. Nothing in the repo sets that scope.This merge cannot be the cause: it changed zero dependency manifests.
pnpm-lock.yamlis byte-identical tomain, and the onlydesktop/package.jsonchange is upstream's0.5.14→0.5.15version field.The 9
tscerrors follow from it — all areTS2307 Cannot find moduleforstarknetand@the-situation/*, in four fork-local files:Those modules are absent from the local
node_modulesbecause the install is blocked. The merge touches no file underdesktop/src/features/markets/, and there are no typecheck errors anywhere else in the tree. CI, which installs with its own credentials, is the real signal here.Mobile gates (
dart format,flutter analyze,flutter test) were not run: upstream changed no file undermobile/, and the merge introduces none.Needs a human look
The sidebar Markets row is an undocumented fork patch site.
desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsxcarries a fork-local divergence (the shared Inbox+Markets row, from feat(markets): Bitcoin difficulty betting (hidden L2, Lightning fund only) #31 "Bitcoin difficulty betting") that has no row in theAGENTS.mdpatch table and noFORK-LOCALmarker in the file. It conflicted today and will conflict again whenever upstream touches that row. The wider markets feature — including the@atomiqlabs/*andstarknetdeps indesktop/package.json— is similarly undocumented. Deliberately not added to the table in this PR, because changing the patch table is itself a merge tripwire and this is a pre-existing gap rather than something this sync created; recording it is a separate call.Markets button now dims when inactive (see Conflicts). Behavioural, small, and consistent with upstream's intent — but it is a visual change to a fork-local surface that no upstream test covers.
The local
pnpm installbreakage is worth fixing at the source — the@atomiqlabsscope should resolve to public npm, not GitHub Packages. Until then, no desktop JS gate that shells throughpnpmcan run locally; the ones above were run by invoking the binaries directly.No wire-format change. No migration. No kind change. No fork patch deleted.