Skip to content

feat(agent): show readiness and capabilities before delegation - #2957

Closed
BradGroux wants to merge 2452 commits into
block:mainfrom
BradGroux:agent/agent-capability-readiness
Closed

feat(agent): show readiness and capabilities before delegation#2957
BradGroux wants to merge 2452 commits into
block:mainfrom
BradGroux:agent/agent-capability-readiness

Conversation

@BradGroux

@BradGroux BradGroux commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Closes #2931.

What this fixes

Buzz currently makes an owner infer whether an agent is ready for local delegation by cross-referencing the agent editor, managed-runtime state, presence, and ACP observer logs. Missing evidence can look like unsupported behavior, while requested and effective permission modes are not visible together.

The important pre-delegation questions should be answerable in one place: is this local process healthy, which runtime and model are active, which features and tools were actually reported, how risky are those tools, and is the evidence from the current process and session?

What changes

The owner-only Runtime tab now includes a readiness and capability manifest built from four existing evidence sources:

  • the ACP runtime catalog for installation, authentication, adapter, and static runtime facts;
  • managed lifecycle state for the current process and community connection;
  • current presence;
  • the encrypted owner observer stream for ACP initialize, session configuration, commands, tools, model, protocol, and permission evidence.

The card shows installation, authentication, process, community, presence, observer readiness, runtime and model facts, prompt and output features, commands, MCP source names, tool descriptors and risk classes, requested and effective permission modes, evidence source, divergence, freshness, and known limitations.

The reducer treats absent or malformed evidence as unknown. Evidence is retained independently of the capped raw transcript, but it is invalidated across process and session boundaries. A stopped process, failed lifecycle, offline presence, closed observer, or initialize event from an older process cannot produce a ready state.

Trust boundary

This is local owner evidence, not a public capability, safety, or reputation claim. The UI says “Runtime ready” and identifies the owner-and-machine scope.

The harness projects only MCP server names and permission semantics. It does not forward MCP commands, arguments, environment values, credentials, executable paths, raw lifecycle errors, or config values.

Desktop parsing is strict and bounded. Older Desktop backends that do not report the new static fields remain compatible and render those facts as unknown. A non-owner E2E regression test verifies that neither the Runtime tab nor the manifest is exposed.

Verification

  • Rebased onto current main at 5bf78671f45178f8de02ba18d3d321cbbf19cd1f; the current PR head is d53016c8490f1c0675b4dc56ac033bb7c9f29084.
  • Resolved the permission conflict in favor of current main's auto-approval behavior while retaining the manifest's requested/effective permission evidence and corrected fallback wording.
  • cargo test -p buzz-acp --lib passes 689 tests after removing an unrelated inherited BUZZ_ACP_LAZY_POOL environment override.
  • The prior full branch verification passed Rust formatting and Clippy, Desktop/web checks and builds, Rust package tests, Desktop and Tauri suites, focused owner/non-owner Playwright coverage, and rendered-card inspection. Its one mobile failure reproduced identically on clean main and did not touch this PR's files.

Non-goals

  • No public or portable capability attestation.
  • No observation receipt, capability digest, or shareable claim envelope.
  • No third-party reputation or protocol integration.
  • No arbitrary wall-clock TTL; freshness is bound to the current healthy process, observer connection, session, presence, and community evidence.
  • No automatic delegation or permission-policy change.
  • No storage of secrets, full runtime configuration, or raw observer payloads.

@BradGroux
BradGroux requested a review from a team as a code owner July 26, 2026 07:02
BradGroux added a commit to BradGroux/buzz that referenced this pull request Jul 26, 2026
@BradGroux

BradGroux commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Updated screenshots

Readiness and runtime evidence

The owner can see the six readiness gates alongside runtime, ACP protocol, requested model, applied model, provider evidence, and the explicit local-only trust boundary.

Readiness and runtime evidence

Capabilities, permissions, and tools

Reported, unavailable, and unknown states remain distinct. Requested and effective permission modes are shown with their evidence source, followed by commands, MCP source names, and tool risk classes.

Capabilities, permissions, and tools

Complete manifest

The full card uses “Ready locally” and states that the evidence is for this owner and machine, not a public safety or reputation claim.

Complete agent capability manifest

@BradGroux

Copy link
Copy Markdown
Contributor Author

Feedback review and current-main refresh

The external feedback was posted on the linked issue, #2931, rather than in a PR review thread. I rechecked the suggestion against the issue scope and the current implementation.

The central point was valid: local runtime readiness must not be presented as a portable safety, reputation, or third-party delegation claim. The existing branch already incorporates the supported parts:

  • The card says “Ready locally” and scopes the evidence to this owner, machine, running process, observer connection, community, and ACP session.
  • Requested and effective permission modes are separate, with the policy source identified.
  • Model evidence distinguishes requested, applied, reported, and configured state.
  • Missing evidence remains unknown rather than being treated as unsupported or safe.
  • MCP output is limited to redacted source names and explicit runtime-provided descriptors; commands, arguments, environment values, credentials, prompts, paths, and tool content are excluded.

I did not add runtime_observation_id, capability_set_digest, a portable claim_scope, or an arbitrary wall-clock freshness window. Those require a separately specified authenticated receipt contract with issuer, verifier, expiry, and replay semantics. Adding the labels here would imply portability that this owner-local evidence does not have. The detailed original disposition remains in the issue follow-up.

I have now refreshed this PR onto current main:

  • New head: ccd194bbc9c54608fba18faaafcf00ab75038393
  • Current base: 6da45ac5cf90fa0768a98256e2200708d219ddfc
  • git range-diff reports all three rebased commits as patch-equivalent; there are no new feature-code changes.

bin/just ci at the new head passed workspace Rust formatting and Clippy, Desktop/web checks and builds, the repository Rust unit suites, 3,739 Desktop tests, and 1,815 Tauri tests plus 3 mixer diagnostics. The mobile suite reached 861 passing tests with one skipped and stopped on keeps follow mode off while a tall newest message stays visible. The same focused test fails identically on clean current main at 6da45ac5cf90fa0768a98256e2200708d219ddfc, and this PR changes no mobile files.

The refreshed head is mergeable. GitHub checks are running again against the new commit.

@BradGroux BradGroux changed the title Show agent readiness and capabilities before delegation feat(agent): show readiness and capabilities before delegation Jul 29, 2026
@BradGroux
BradGroux force-pushed the agent/agent-capability-readiness branch from ccd194b to 3173cf4 Compare July 30, 2026 14:37
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebased this branch onto current block/buzz main at c55e421a0 and adapted it to current repository limits.

Head moved from ccd194bbc to 3173cf4dd. The agent contributor rules retain the newly landed shared-agent access rule and place this PR's evidence-only capability-manifest rule after it. The runtime capability fields were also split into focused Rust and TypeScript modules so the branch satisfies the current base-tree file-size ratchet without weakening that gate; the serialized IPC keys remain unchanged.

Verification:

  • Full buzz-acp suite passed: 643 library tests and 9 pool tests.
  • Strict Clippy passed for buzz-acp with all targets and warnings denied.
  • Tauri compile check passed.
  • Tauri tests passed: 1,878 library tests plus 3 mixer diagnostics; 14 keychain/relay-dependent tests remained explicitly ignored.
  • Strict Tauri Clippy passed with all targets and warnings denied.
  • Desktop Biome, file-size, text-size, and pubkey-truncation checks passed.
  • The full Desktop test suite, TypeScript typecheck, and production Vite build passed on the final rebased branch.
  • git diff --check, DCO trailer checks, and the direct merge-base audit passed.

GitHub checks are rerunning on the new head.

@BradGroux

Copy link
Copy Markdown
Contributor Author

Current-main refresh and permission-boundary follow-up

I reviewed the new enforcement-boundary feedback on linked issue #2931 and refreshed this branch onto current main.

The architecture decision is that AcpClient::handle_permission_request is Buzz's narrow generic cooperative seam, not a universal enforcement or containment boundary. This PR therefore remains scoped to readiness and evidence display; it does not add attestation or policy-enforcement code. The detailed boundary response is on the linked issue.

Rebase update:

  • Current head: 278151c48ca17c908c1123a1d57c18122c1b727f
  • Current base: b1b283cd4c7f926e12eeee8ae1f38c7471922b16
  • Current main moved preset runtime capability defaults into a separate module. The refreshed branch restores the missing default capability facts to preset runtime entries so the readiness manifest retains the expected evidence after the rebase.
  • GitHub reports the refreshed head mergeable and waiting on required review.

Verification on the refreshed head:

  • Desktop: 3,903 tests, typecheck, and production build passed.
  • buzz-acp: 664 library tests and 9 pool-lifecycle tests passed.
  • Tauri: 2,048 library tests plus 3 mixer diagnostics passed.
  • Affected formatting, Clippy, compile-check, typecheck, and build gates passed.
  • just ci passed every earlier stage before the unchanged mobile suite failed on ChannelDetailPage keeps follow mode off while a tall newest message stays visible. A full mobile retry reproduced the failure, and this PR has no mobile diff.
  • DCO, Semgrep OSS, and zizmor are green on the live head.

The remaining limitation is unchanged: any future policy at session/request_permission would govern only cooperative operations that cross that request. Direct runtime filesystem, subprocess, network, and MCP paths remain outside that guarantee.

@BradGroux
BradGroux force-pushed the agent/agent-capability-readiness branch from 278151c to 0a79898 Compare August 4, 2026 20:36
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebased onto block/buzz main at ce3cf3cd2591f132f286fbc0a42a9e6699d0b08d and re-audited the linked-issue feedback, current capability-policy work, and the branch's local trust boundary.

The feedback remains partially valid: local runtime readiness must not be presented as portable attestation, third-party reputation, or a universal permission-enforcement boundary. This branch already applies that constraint. The UI says “Ready locally,” scopes evidence to this owner, machine, process, observer connection, community, and ACP session, keeps missing evidence unknown, and separates requested from effective permission state. I did not add portable digests, observation receipts, arbitrary expiry semantics, or policy enforcement because those require a separately specified authenticated contract. #4066, #4540, and #4333 cover adjacent permission, onboarding, and Guardian policy work; none supplies this owner-local evidence surface. The PR therefore remains valid and was not closed.

The rebase required manual integration in managed-runtime types, the profile Runtime tab, and the Tauri API boundary. It preserves the newer config-diff, model-tuning, trading-card, media, and runtime-catalog fields already on main, including token, context-limit, and round-limit metadata. The capability facts remain in focused modules so the current file-size ratchet stays intact.

Exact-head verification on 0a798985a2cebb1e7efc1e319b7dd7b121eb2291:

  • Full buzz-acp suite passed with the ambient lazy-pool override removed: 671 library tests and 9 pool-lifecycle tests, 0 failures.
  • Root Rust formatting passed, and strict buzz-acp Clippy passed with all targets, all features, and warnings denied.
  • Desktop policy/static checks, the full JavaScript suite, typecheck, production build, and E2E build passed.
  • Focused owner and non-owner Playwright coverage passed: 2 tests, including verification that the manifest is not exposed to a non-owner.
  • Tauri formatting and cargo check passed.
  • Full Tauri suite passed: 2,205 library tests plus 3 mixer diagnostics, 0 failures; 13 library tests and the native latency gate remained explicitly ignored.
  • Strict Tauri Clippy passed with all targets and warnings denied.
  • git diff --check, conflict-marker scan, merge-base audit, and required DCO trailers passed.

The remaining boundary is deliberate: cooperative ACP permission requests are observable evidence, not proof that direct runtime filesystem, subprocess, network, or MCP paths are contained. This PR does not automate delegation or change permission policy.

@BradGroux
BradGroux force-pushed the agent/agent-capability-readiness branch from 0a79898 to 8fc6962 Compare August 5, 2026 22:26
@BradGroux

Copy link
Copy Markdown
Contributor Author

Review and rebase summary

Reviewed the PR for accuracy against current block/buzz main at d42d60d64 and rebased the branch onto that commit. This rebase required manual conflict resolution — the previous head was CONFLICTING with main.

What this PR does

Adds a capability readiness manifest to the agent profile panel: an owner-only "Runtime" tab that surfaces six readiness gates (community, observer, runtime catalog, ACP protocol, model, permissions) alongside the runtime's tool sources, permission mode, and model application status. The manifest is populated from three evidence streams: the static runtime catalog, lifecycle observer events, and session_config_captured observer frames. A capabilityManifest field is added to the session_config_captured observation, carrying a safe projection of model application, tool sources, and permission mode — no MCP commands, arguments, env vars, paths, or credentials enter it.

Accuracy review

  • The build_session_config_observation function correctly distinguishes requested vs. effective permission mode, including the buzzHarness fallback (perToolAutoDecision) when no runtime mode was applied. This is honest about what the harness actually does rather than claiming the runtime's built-in mode is known.
  • The apply_model_switch and apply_permission_mode functions now return Result<bool, AcpError> instead of Result<(), AcpError>, so session_config_captured can report whether the model switch actually applied vs. silently falling back. Transport errors remain fatal; application errors return false.
  • The set_observer_session_id method attaches the session ID immediately after session/new so later model/mode calls cannot be mistaken for evidence from a prior session.
  • The desktop AcpRuntimeCatalogEntry type now carries AcpRuntimeCapabilityFacts (via #[serde(flatten)]) with supports_acp_native_config, supports_acp_model_switching, and mcp_hooks. The refactor into runtime_catalog.rs and tauriAcpRuntimeCatalog.ts keeps the file under the 1000-line limit.
  • The E2E test verifies the owner sees the manifest and a non-owner does not get the "Runtime" tab.
  • No unwrap() or expect() in production paths. No new dependencies.

Conflict resolution

Seven files conflicted during rebase. The main-line changes that caused conflicts were:

  1. pool.rsmain changed the permission-mode comment from "auto-approves via handle_permission_request" to "rejects interactive permission requests." The PR's let permission_mode_applied = if ... pattern and build_session_config_observation function were preserved; the comment was updated to match main's wording.
  2. types.rs, discovery.rs, agent_discovery.rs, presets.rsmain added a max_parallelism field to AcpRuntimeCatalogEntry. The PR's refactor moved the struct to runtime_catalog.rs and used AcpRuntimeCapabilityFacts for the capability fields. Resolution: kept the PR's module split, added max_parallelism to the moved struct, and used capabilities: runtime.into() / capabilities: Default::default() at construction sites alongside max_parallelism.
  3. tauri.ts, types.ts — same split: the RawAcpRuntimeCatalogEntry type and fromRawAcpRuntimeCatalogEntry function were moved to tauriAcpRuntimeCatalog.ts; max_parallelism was added to both the raw type and the mapping function. The AcpRuntimeCatalogEntry TS type now intersects AcpRuntimeCapabilityFacts and carries maxParallelism.

Rebase result

Head moved from 0a798985a to 8fc6962ae. Five commits, all cleanly rebased. The PR is now MERGEABLE (previously CONFLICTING).

CI

DCO passes. Semgrep OSS and zizmor were pending at the time of this comment.

@BradGroux
BradGroux force-pushed the agent/agent-capability-readiness branch from 8fc6962 to db61837 Compare August 7, 2026 21:03
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebase and accuracy review (2026-08-07)

Rebased onto current main (2b873cf20). Conflict resolved — 52 commits applied, 1 file conflicted.

Branch state: db61837d6 (was 8fc6962ae) Mergeable: ✅ MERGEABLE · BLOCKED (branch protection — awaiting maintainer review)

Conflict resolution

desktop/src/features/agents/AGENTS.md — main added the owner-only-access build capability paragraph (item 11), while the branch added a new item 12 for capability manifest evidence semantics. Resolution: kept both items in order — main's item 11 (owner-only-access) followed by the branch's item 12 (capability manifests project evidence). No content lost.

During the rebase, the second and third commits in the series also had minor AGENTS.md conflicts in the test-enforcement section. These were resolved by taking the branch version (adding the new test entries for capabilityManifest.test.mjs and AgentCapabilityManifestCard.render.test.mjs).

Accuracy review

The PR adds a capability/readiness manifest system that projects KnownAcpRuntime facts, managed-agent lifecycle, presence, and the encrypted owner observer stream into an owner-facing UI. The evidence model is sound: missing fields are unknown, explicit false is unavailable, and only a supplied fact is reported. Manifest projection is allowlist-only — no raw config, commands, env vars, or credentials are surfaced.

The 5-commit series is well-structured: initial feature, evidence hardening, catalog checks, file-limit refactor, and a final preset fix. Tests cover evidence semantics, staleness, permission divergence, safe tool projection, and observation ordering. No unwrap()/expect() in production paths. No new dependencies.

Scope is broad (21 files, ~3100 insertions) but cohesive — the module split into tauriAcpRuntimeCatalog.ts and the runtime_catalog.rs refactor are clean.

wpfleger96 and others added 6 commits August 7, 2026 15:05
…rride (block#5242)

## Problem

Two v0.5.6-only regressions were introduced by block#4614 (the first enforced
Tauri CSP):

1. **Tab-complete caret regression** — after tab-completing an @mention,
#channel, or :emoji: shortcode, the cursor landed inside the inserted
text instead of after the trailing space. TipTap inserts the correct
text including the trailing space, but without its base stylesheet
(`.ProseMirror { white-space: break-spaces }`) the trailing space
collapses visually and the caret appears mid-name.

2. **Emoji picker unstyled** — the emoji-mart picker rendered as a giant
unstyled layout (oversized search SVG, collapsed grid) because
emoji-mart's shadow-root stylesheet injection was also blocked.

Both symptoms have the same root cause.

## Root Cause

Tauri's build-time asset processor scans `index.html` for inline
`<style>` elements, injects a nonce token, and adds the corresponding
`'nonce-…'` source to `style-src` at runtime. Per the CSP spec, **once a
nonce is present in a directive, the browser ignores `'unsafe-inline'`
for that directive**.

`index.html` contained an inline `<style>` with the boot background
color. When Tauri nonced it and injected `'nonce-…'` into `style-src`,
the intended `style-src 'self' 'unsafe-inline'` became effectively
`style-src 'self' 'nonce-…'` — blocking any runtime stylesheet injection
not covered by a matching nonce:

- TipTap's `injectCSS()` → `createStyleTag()` injecting `.ProseMirror {
white-space: break-spaces; … }`
- emoji-mart's shadow-root `document.createElement('style')` injection

(Inline scripts follow a separate path — they are SHA-256 hashed, not
nonced.)

This only reproduces in packaged builds (where Tauri's custom protocol
serves the HTML and enforces the policy). `tauri dev` loads from the
Vite dev server and is not affected.

## Fix

Move `html { background-color: #000; }` from an inline `<style>` in
`index.html` to `desktop/public/boot.css`, linked via `<link
rel="stylesheet">`. A linked stylesheet is not subject to Tauri's nonce
injection, so `'unsafe-inline'` in `style-src` applies as declared.

The `<link>` is render-blocking (same as the inline style was), so
boot-flash behaviour is identical.

**The production CSP string is unchanged.** This fix makes the policy
apply as intended — no security properties are altered. Will's follow-up
with the security team (Jordan Mecom / Eli Foster, authors of block#4614) is
noted for post-ship.

A Tauri-faithful CSP harness for the Vite dev path (so this class of
regression is visible before a packaged build) is tracked as a separate
follow-up.

## Files Changed

- `desktop/index.html` — replace inline `<style>` with `<link
rel="stylesheet" href="/boot.css" />`
- `desktop/public/boot.css` — new file, the extracted `html {
background-color: #000; }` plus rationale comment
- `desktop/src-tauri/tests/csp.rs` — update comment: nonce for styles,
SHA-256 for the boot script

## Testing

- `just desktop-typecheck` ✅
- `just desktop-test` ✅ (4535/4535)
- `just desktop-tauri-test` ✅ (all Rust tests including `csp.rs`)
- Packaged validation: `pnpm tauri build --debug` completed; compiled
binary bakes `style-src 'self' 'unsafe-inline'` with no nonce source
injected ✅

---------

Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
## Summary

- serialize the relay error-message test with all other tests mutating
the process-wide admission gate
- clear its 300-second rate-limit expiry after the assertion
- prevent the paused-time waiter test from observing another test's
state

## Root cause

`relay::tests::oversized_hint_is_capped_in_relay_error_message_string`
arms the process-wide gate for 300 seconds without taking `TEST_SERIAL`
or resetting it. In a parallel test run,
`relay_admission::tests::concurrent_429_extends_the_window_for_parked_waiters`
can observe that expiry, producing the reported `300.001s` instead of
`5s`.

## Validation

- focused admission suite + relay error test repeated 10 times
- pre-push `desktop-tauri-checks` passed, including the full Rust
workspace suite
- `branch-skew` passed

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

- **Frozen main:** `cf0967517ce6545903089939acfa7eefdc1e8696`
- **Reviewed candidate:** `c1972d72b0b80168d0ec8ff7c935d662c6586a0f`
- **Previous desktop release:** `desktop-v0.5.6`
- **Proposed immutable tag:** `desktop-v0.5.7`

This PR may be **squash merged** after the Desktop Release Candidate
check and all protected-branch checks pass. Merging authorizes
publication of the exact reviewed candidate; later or unrelated changes
on `main` cannot alter it.

The checked-in changelog accounts for every non-merge commit in the
release range. The Desktop tag points to the reviewed candidate commit,
not the later squash commit. Publication remains bound to that immutable
candidate tag.

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Release Automation <release-automation@users.noreply.github.com>
## What changed

Bind the development Compose stack's published PostgreSQL, Redis,
Adminer, Keycloak, MinIO, and Prometheus ports to `127.0.0.1`.

## Why

Docker publishes a host port on every interface when no host address is
specified. Running the development stack on a remote workstation or VPS
therefore exposes its infrastructure services to that machine's public
networks. Loopback bindings retain host-local development access and
Docker's internal `buzz-net` connectivity without making those services
Internet-reachable.

## Impact

Local workflows continue using the same ports. Deliberate remote
administration now requires an SSH tunnel or another trusted
private-network path.

## Validation

- `docker compose -f docker-compose.yml config --quiet`
- Recreated the six affected services with their existing named volumes
and Docker network
- PostgreSQL remained healthy and retained all 54 application tables
- Redis, MinIO, and Prometheus health checks passed
- All affected ports were closed on the host's public IPv4 and IPv6
addresses while remaining available on loopback

Origin:
`buzz://message?channel=199eb7bc-3feb-484f-ae0e-4995123721ea&id=1c5bc387e86e21bb31677f56e1c862d4d9a17943bce91f8d93e825d029ce7f72`

Signed-off-by: Paweł Karniej <karniej.p@gmail.com>
…starve the handoff summary (block#5248)

## Problem

The handoff summarizer sends `max_tokens: 8192`
(`HANDOFF_MAX_OUTPUT_TOKENS`) with no reasoning budget separation. On
reasoning models, thinking tokens count against that cap: the model can
spend the entire budget reasoning, length-stop with empty `content`, and
`summarize()` — which only reads `content` — reports an empty summary.
The handoff then degrades to lossy history truncation.

Observed on deepseek-v4-flash during a terminal-bench 2.1 run
(tb21-solo-3, 89 tasks): **13 consecutive handoff attempts across 5
trials failed exactly this way** (`handoff returned empty summary;
truncating`), each burning ~3 minutes of full-cap reasoning, before a
stochastically-short reasoning run finally fit. circuit-fibsqrt alone: 5
failures, 5 truncations, then success on attempt 6. video-processing
failed its task by one frame after 3 context truncations.

## Fix

`openrouter_summary_body` now grants reasoning its own equal-sized
budget and excludes it from the response:

- `reasoning.max_tokens = max_output_tokens` — thinking gets a dedicated
budget instead of competing with the summary text
- `reasoning.exclude = true` — reasoning is never in the response body;
`summarize()` only reads `content`
- `max_tokens = max_output_tokens * 2` — the total cap covers both
budgets, so the text budget the caller asked for is actually available
for text

Non-reasoning endpoints ignore the `reasoning` object. Deliberately not
paired with `provider.require_parameters`, for the reasons documented at
`apply_openrouter_mutations` (it hard-404s valid model ids).

The prior test
`openrouter_summary_carries_neither_reasoning_nor_provider` asserted
`reasoning` absent from the summary body — that assertion guarded
against *effort-based* reasoning leaking in from config (the body is
built independently of `cfg`, which is still true and still tested:
`reasoning.effort` stays unset). Replaced with
`openrouter_summary_budgets_reasoning_separately_and_carries_no_provider`.

## Verification

- `cargo test -p buzz-agent`: 422 unit + 110 integration tests pass at
bb2fedd
- `cargo fmt` / `cargo clippy -p buzz-agent --all-targets`: clean
- Not yet validated against a live OpenRouter reasoning endpoint — the
failing scenario needs a long-context session to trigger organically.
Evidence for the mechanism is from run artifacts (13/13 empty-summary
length-stops on deepseek-v4-flash) and OpenRouter's documented
`reasoning.max_tokens`/`reasoning.exclude` semantics.

---------

Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
**Category:** improvement
**User Impact:** Users can create, discover, and import agents from one
consistent Add agent dialog.

**Problem:** Agent creation, discovery, and import were split across a
dropdown and separate dialogs, making the Add agent flow fragmented. The
existing E2E suite also continued targeting the deleted dropdown after
the flows were unified.

**Solution:** Route the new-agent card directly into a unified dialog
with dedicated Create, catalog, and Import navigation, then update the
affected E2E coverage to exercise that interface and its current empty
state.

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

**desktop/src/features/agents/ui/AgentDefinitionDialog.tsx**
Supports rendering the agent definition form inside the unified Add
agent experience while retaining the standalone dialog behavior.

**desktop/src/features/agents/ui/AgentDefinitionDialogShell.tsx**
Adds the shared shell used to present agent-definition content
consistently in embedded and standalone contexts.

**desktop/src/features/agents/ui/AgentDialog.tsx**
Passes the revised dialog state and close behavior through the existing
agent dialog entry point.

**desktop/src/features/agents/ui/AgentsView.tsx**
Connects the Agents page to the unified Add agent dialog and opens newly
added catalog agents in their profile panel.

**desktop/src/features/agents/ui/PersonaCatalogDialog.tsx**
Combines catalog browsing, agent creation, and snapshot import behind
persistent navigation, including dirty-navigation confirmation.

**desktop/src/features/agents/ui/UnifiedAgentsSection.tsx**
Replaces the new-agent dropdown with a direct Add agent entry point and
adjusts the responsive card grid.

**desktop/src/features/agents/ui/personaLibraryCopy.ts**
Updates catalog-facing copy for the unified experience.

**desktop/src/features/agents/ui/usePersonaActions.ts**
Returns the resolved local persona after catalog activation so the
caller can open the added agent.

**desktop/tests/e2e/agent-readiness-screenshots.spec.ts**
Opens the embedded create pane directly for readiness screenshots.

**desktop/tests/e2e/agents.spec.ts**
Covers unified Create, catalog, and Import navigation and asserts the
current shared-agent empty state.

**desktop/tests/e2e/global-agent-config-screenshots.spec.ts**
Updates global configuration screenshot setup for direct create-pane
entry.

**desktop/tests/e2e/inline-custom-harness.spec.ts**
Updates custom harness setup for the embedded create form.

**desktop/tests/e2e/persona-env-vars.spec.ts**
Updates environment-variable and model-provider scenarios for direct
create-pane entry.

**desktop/tests/e2e/persona-model-combobox-screenshots.spec.ts**
Updates model combobox screenshot setup for direct create-pane entry.

**desktop/tests/e2e/smoke.spec.ts**
Updates agent-creation smoke coverage for the unified Add agent dialog.

**desktop/tests/e2e/where-to-run-config.spec.ts**
Updates provider-selection coverage for the embedded create form.

</details>

## Reproduction steps

1. Open the Agents page and select the new-agent card.
2. Confirm the Add agent dialog opens directly on Create without an
intermediate dropdown.
3. Use the left navigation to browse shared agents and open Import.
4. Select a catalog agent and confirm the dialog closes and the added
agent's profile panel opens.
5. Run the affected desktop Playwright smoke and integration specs and
confirm all scenarios pass.

---------

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
@wolfyy970

Copy link
Copy Markdown

I think this should be the agent-session half of #5060. The local evidence boundary is right: a Project connection being healthy does not prove it was applied to this agent.

Rather than build another readiness surface, I would join the existing pieces here:

The missing seam is a non-secret binding identity and generation in the launch observation. That would let the UI distinguish Configured, Ready at Project, Applied to agent, and Observed in session without exposing endpoints or credentials.

I will keep the portable-agent side limited to desired capability requirements and let this surface own applied and observed evidence.

renovate Bot and others added 22 commits August 21, 2026 18:28
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [http](https://redirect.github.com/hyperium/http) | dependencies |
patch | `1.4.0` → `1.4.2` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](..block/issues/1) for more information.

---

### Release Notes

<details>
<summary>hyperium/http (http)</summary>

###
[`v1.4.2`](https://redirect.github.com/hyperium/http/blob/HEAD/CHANGELOG.md#142-June-8-2026)

[Compare
Source](https://redirect.github.com/hyperium/http/compare/v1.4.1...v1.4.2)

- Fix `uri::Builder` to allow `"*"` as the path when scheme and
authority are also set, used in HTTP/2 requests.
- Fix `Uri` to properly reject `DEL` characters.

###
[`v1.4.1`](https://redirect.github.com/hyperium/http/blob/HEAD/CHANGELOG.md#141-May-25-2026)

[Compare
Source](https://redirect.github.com/hyperium/http/compare/v1.4.0...v1.4.1)

- Fix `PathAndQuery::from_static()` and `from_shared()` to reject inputs
that do not start with `/`.
- Fix `Extend` for `HeaderMap` to clamp max size hint and not overflow.
- Fix `header::IntoIter` that could use-after-free if the generic value
type could panic on drop.
- Fix `header::{IterMut, ValuesIterMut}` to not violate stacked borrows.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/block/buzz).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [http-body-util](https://redirect.github.com/hyperium/http-body) |
dependencies | patch | `0.1.3` → `0.1.5` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](..block/issues/1) for more information.

---

### Release Notes

<details>
<summary>hyperium/http-body (http-body-util)</summary>

###
[`v0.1.5`](https://redirect.github.com/hyperium/http-body/compare/http-body-util-v0.1.4...http-body-util-v0.1.5)

[Compare
Source](https://redirect.github.com/hyperium/http-body/compare/http-body-util-v0.1.4...http-body-util-v0.1.5)

###
[`v0.1.4`](https://redirect.github.com/hyperium/http-body/releases/tag/http-body-util-v0.1.4)

[Compare
Source](https://redirect.github.com/hyperium/http-body/compare/http-body-util-v0.1.3...http-body-util-v0.1.4)

#### What's Changed

- Add `Fused` body combinator that always returns `None` once completed.
- Add `BodyExt::into_stream()` to convert a body into a `Stream`.
- Add `Full::into_inner()` to get the full `Buf`.
- Add `InspectFrame` and `InspectErr` combinators.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/block/buzz).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMi4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [sonner](https://sonner.emilkowal.ski/)
([source](https://redirect.github.com/emilkowalski/sonner)) | [`2.0.7` →
`2.0.8`](https://renovatebot.com/diffs/npm/sonner/2.0.7/2.0.8) |
![age](https://developer.mend.io/api/mc/badges/age/npm/sonner/2.0.8?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/sonner/2.0.7/2.0.8?slim=true)
|

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](..block/issues/1) for more information.

---

### Release Notes

<details>
<summary>emilkowalski/sonner (sonner)</summary>

###
[`v2.0.8`](https://redirect.github.com/emilkowalski/sonner/compare/v2.0.7...ecce1841c55e4a72dfe139a8992b56498660125e)

[Compare
Source](https://redirect.github.com/emilkowalski/sonner/compare/v2.0.7...v2.0.8)

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/block/buzz).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4yOS41IiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [async-trait](https://redirect.github.com/dtolnay/async-trait) |
dependencies | patch | `0.1.91` → `0.1.92` |

---

> [!WARNING]
> Some dependencies could not be looked up. Check the [Dependency
Dashboard](..block/issues/1) for more information.

---

### Release Notes

<details>
<summary>dtolnay/async-trait (async-trait)</summary>

###
[`v0.1.92`](https://redirect.github.com/dtolnay/async-trait/releases/tag/0.1.92)

[Compare
Source](https://redirect.github.com/dtolnay/async-trait/compare/0.1.91...0.1.92)

- Resolve double\_must\_use clippy lint in generated code
([#&#8203;303](https://redirect.github.com/dtolnay/async-trait/issues/303))

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/block/buzz).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4yOS41IiwidXBkYXRlZEluVmVyIjoiNDQuMzkuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…ock#6531)

**Category:** fix
**User Impact:** Users can insert mentions earlier in a draft and
continue typing without the caret corrupting the rest of the message.

**Problem:** Caret correction ran after every document change, so typing
a mention before existing text repeatedly advanced across the mention
separator and interleaved spaces into the draft. **Solution:** Limit
correction to the autocomplete settlement it was designed for, with
transaction-level and browser-level regression coverage for known and
unregistered mentions.

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

**desktop/src/features/messages/lib/mentionHighlightExtension.ts**
Restricts trailing-space caret advancement to an armed autocomplete
settlement instead of every document change.

**desktop/src/features/messages/lib/mentionHighlightExtension.test.mjs**
Exercises the real ProseMirror plugin state and verifies mid-draft
mention typing, unknown tokens, end-of-message typing, and
completed-mention separators.

**desktop/tests/e2e/mentions.spec.ts**
Reproduces the reported composer workflow in Chromium and covers the
same corruption path for an unregistered `@token`.

</details>

## Reproduction steps

1. Open a channel and enter `hello world` in the composer.
2. Move the caret between `hello` and ` world`.
3. Type ` @bo`, select `bob` from autocomplete, and continue typing
`abc`.
4. Confirm the composer reads `hello @bob abc world` with the caret
after `abc`.
5. Repeat with an unregistered token such as ` @zzq` and confirm the
existing text remains intact.

## Before / After

| Before | After |
| --- | --- |
| Typing after a mid-draft mention walks the caret through the existing
message. | Continued typing stays after the inserted mention. |
| ![Before: mention caret corrupts existing draft
text](https://d24qwcpro867f5.cloudfront.net/repos/buzz/prs/6531/mention-caret-before.gif)
| ![After: caret remains after the inserted
mention](https://d24qwcpro867f5.cloudfront.net/repos/buzz/prs/6531/mention-caret-after.gif)
|

---------

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Mongo <5398c5fd039b963ce132b3e078e7c4af097dd997517bb5e14c2682fe68c25197@buzz.block.builderlab.xyz>
**Category:** improvement
**User Impact:** Buzz-native project, repository, issue, and pull
request links now appear once as compact inline chips, with their
details available on hover.

**Problem:** Buzz-native entity links rendered both an inline chip and a
standalone preview card, repeating the same metadata and adding visual
noise to conversations. **Solution:** Exclude Buzz-native links from the
shared standalone-preview extractor while leaving entity parsing intact
for chip tooltips and preserving external web previews and attachment
cards.

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

**desktop/src/shared/lib/linkPreview.ts**
Stops Buzz-native preview candidates after parsing, including same-relay
git clone URLs that normalize to repository entities, while allowing
external URLs through the existing snapshot path.

**desktop/src/shared/lib/linkPreview.test.mjs**
Covers project, repository, issue, pull request, markdown-labeled,
same-relay clone, and mixed external-link extraction behavior.

**desktop/src/shared/ui/markdown/useMessageLinkPreviews.test.mjs**
Confirms sent messages no longer merge a standalone Buzz entity card
while external sender snapshots still render.

</details>

## Reproduction steps

1. Open a desktop channel containing a `buzz://project`, `buzz://repo`,
`buzz://issue`, or `buzz://pr` link.
2. Confirm the link renders as an inline entity chip without a second
standalone Buzz card below the message.
3. Hover the chip and confirm its entity metadata remains available.
4. Post an external HTTPS link and confirm its web preview still
renders.
5. Paste a same-relay `/git/<owner>/<repo>` clone URL and confirm it
uses the repository chip without a duplicate card.

## Screenshots

| Before | After |
| --- | --- |
| Inline chip plus redundant standalone Project card | Inline chip is
now the sole presentation |
| ![Before: project chip and duplicate standalone
card](https://raw.githubusercontent.com/block/buzz/7e1a0d6cfb52382ef636d7331cf30ea334429c4d/pr-6512--before.png)
| ![After: project chip without a standalone
card](https://raw.githubusercontent.com/block/buzz/7e1a0d6cfb52382ef636d7331cf30ea334429c4d/pr-6512--after.png)
|

**After — rich metadata stays available on hover**

![After: dark theme with pink accent and Project tooltip showing
description and repository
count](https://raw.githubusercontent.com/block/buzz/7e1a0d6cfb52382ef636d7331cf30ea334429c4d/pr-6512--after-tooltip-rich.png)

## Verification

At commit `3fa74cdd342ac1f6721b7d56a7f111af31e0e6e9`:

- focused link-preview + Markdown unit suites — 119/119 passed
- targeted registered smoke E2E — 8/8 passed, including labeled
same-relay clone metadata, ordinary-link presentation, and in-app
navigation
- `cd desktop && pnpm exec tsc --noEmit` — passed
- `git diff --check origin/main...HEAD` — passed
- pre-push hooks — desktop check, TypeScript, and full desktop unit
suite passed

---------

Signed-off-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz>
Co-authored-by: Mongo <5398c5fd039b963ce132b3e078e7c4af097dd997517bb5e14c2682fe68c25197@buzz.block.builderlab.xyz>
…6315)

**Category:** new-feature
**User Impact:** Users can keep selected agents addressed across
consecutive messages without retyping their handles.

**Problem:** Repeated conversations with agents require manually typing
the same mentions on every turn, which adds friction and makes
recipients easy to omit.

**Solution:** The composer can now keep agents automatically addressed
per channel, either from the mention controls or after a successful
inline mention. Addressed agents remain visible in the toolbar, apply to
channel threads, survive send failures safely, and never cross community
boundaries.

## Changes

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

**desktop/src-tauri/src/events/message_tags.rs**  
Preserves the automatic-address marker on validated mention reference
tags.

**desktop/src/features/channels/ui/ChannelPane.tsx**  
Wires the appropriate channel, thread, inbox, or forum composer context
without leaking audiences across surfaces.

**desktop/src/features/communities/useCommunityInit.ts**  
Clears composer audience state when the active community changes.

**desktop/src/features/forum/ui/ForumComposer.tsx**  
Wires the appropriate channel, thread, inbox, or forum composer context
without leaking audiences across surfaces.

**desktop/src/features/forum/ui/ForumComposerAutocompletes.tsx**  
Wires the appropriate channel, thread, inbox, or forum composer context
without leaking audiences across surfaces.

**desktop/src/features/home/ui/InboxDetailPane.tsx**  
Wires the appropriate channel, thread, inbox, or forum composer context
without leaking audiences across surfaces.

**desktop/src/features/messages/lib/agentAddressMention.d.mts**  
Defines helpers and types for marked automatic-address mention tags.

**desktop/src/features/messages/lib/agentAddressMention.mjs**  
Defines helpers and types for marked automatic-address mention tags.

**desktop/src/features/messages/lib/agentAddressMention.test.mjs**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/lib/applyEditTagOverlay.mjs**  
Preserves automatic-address metadata when edited message tags are
overlaid.

**desktop/src/features/messages/lib/applyEditTagOverlay.test.mjs**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.


**desktop/src/features/messages/lib/autoPinMentionedAgentsPreference.test.mjs**
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.


**desktop/src/features/messages/lib/autoPinMentionedAgentsPreference.ts**
Stores the preference that keeps explicitly mentioned agents addressed
for later messages.

**desktop/src/features/messages/lib/extractMentionPersonas.ts**  
Separates persona recipients from the composer mention orchestration.

**desktop/src/features/messages/lib/persistentAgentAudience.test.mjs**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/lib/persistentAgentAudience.ts**  
Maintains bounded, in-memory, channel-scoped automatic agent audiences.

**desktop/src/features/messages/lib/useMentionSelection.ts**  
Centralizes mention picker selection state and agent-first selection
behavior.

**desktop/src/features/messages/lib/useMentions.ts**  
Exposes explicit picker origins and selection controls while preserving
inline mention behavior.

**desktop/src/features/messages/ui/ComposerAddressControls.test.mjs**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/ui/ComposerAddressControls.tsx**  
Renders compact addressed-agent avatars and the automatic-mention
management entry point.

**desktop/src/features/messages/ui/MentionAutocomplete.test.mjs**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/ui/MentionAutocomplete.tsx**  
Adds automatic-mention controls and options to the existing mention
picker.

**desktop/src/features/messages/ui/MessageAgentAddressPrefix.tsx**  
Shows which agents were automatically addressed on a sent message.

**desktop/src/features/messages/ui/MessageComposer.tsx**  
Integrates automatic audiences, picker controls, accessible feedback,
shortcuts, and send behavior.

**desktop/src/features/messages/ui/MessageComposer.types.ts**  
Defines the simplified channel audience context shared by composer
hosts.

**desktop/src/features/messages/ui/MessageComposerToolbar.tsx**  
Places automatic-address controls in the composer toolbar without
crowding narrow layouts.

**desktop/src/features/messages/ui/MessageRow.tsx**  
Displays automatic-address metadata alongside sent message content.

**desktop/src/features/messages/ui/MessageThreadPanel.tsx**  
Wires the appropriate channel, thread, inbox, or forum composer context
without leaking audiences across surfaces.

**desktop/src/features/messages/ui/composerAgentKeyboard.test.mjs**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.


**desktop/src/features/messages/ui/persistentAgentAudienceHosts.test.mjs**
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/ui/useAddressMentionPulse.test.mjs**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/ui/useAddressMentionPulse.ts**  
Provides success and failure animation signals for addressed-agent
controls.

**desktop/src/features/messages/ui/useAgentAddressLockPicker.test.mjs**
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/ui/useAgentAddressLockPicker.ts**  
Coordinates adding, removing, and announcing automatically addressed
agents.

**desktop/src/features/messages/ui/useAlwaysAddressShortcut.ts**  
Implements the platform-aware shortcut for toggling automatic
addressing.

**desktop/src/features/messages/ui/useAutoPinMentionedAgents.ts**  
Promotes successfully sent inline agent mentions and provides a single
undoable notification.

**desktop/src/features/messages/ui/useComposerMentionPicker.ts**  
Opens the mention picker without rewriting the current draft.


**desktop/src/features/messages/ui/useMentionSendFlow.helpers.test.mjs**
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

**desktop/src/features/messages/ui/useMentionSendFlow.helpers.ts**  
Merges automatic and inline recipients, marks outgoing tags, and
restores failed sends safely.

**desktop/src/features/messages/ui/useMentionSendFlow.ts**  
Merges automatic and inline recipients, marks outgoing tags, and
restores failed sends safely.


**desktop/src/features/messages/ui/usePersistentAgentMentionHydration.ts**
Removes the prior draft-text hydration approach now that automatic
audiences stay at composer ingress.

**desktop/src/features/settings/ui/AgentsSettingsPanel.tsx**  
Replaces the old global behavior with explicit composer-level
automatic-mention controls.

**desktop/src/features/settings/ui/PreventSleepSettingsCard.tsx**  
Replaces the old global behavior with explicit composer-level
automatic-mention controls.

**desktop/src/shared/lib/keyboard-shortcuts.ts**  
Defines the user-facing automatic-address keyboard shortcut label.

**desktop/src/shared/ui/VideoReviewCommentMarkdown.tsx**  
Allows automatic-address prefixes to compose with video review
timecodes.

**desktop/tests/e2e/persistent-agent-audience.spec.ts**  
Covers the automatic-address behavior and its failure, keyboard, layout,
or persistence boundaries.

</details>

## Reproduction Steps

1. Open a channel with one or more agents and open the mention picker
from the composer.
2. Select an agent for automatic mentions, then send several messages
without retyping the handle; confirm the agent remains in the composer
control and receives each message.
3. Mention another agent inline, send successfully, and confirm the
agent becomes automatically addressed; use the notification's Undo
action to reverse it.
4. Open a thread in the same channel and confirm the same addressed
agents are available there.
5. Remove an agent from the composer control and confirm later messages
stop addressing it.
6. Switch communities and confirm addressed agents do not carry into the
other community.

## Screenshots

All states below use the dark Buzz theme with a selected lilac accent.

### Addressed composer

Selected agents stay visible at the composer ingress without adding
handles to the draft.

![Two automatically addressed agents in the dark composer with a lilac
accent](https://raw.githubusercontent.com/block/buzz/74c2cbbd80ed630a0c6e00c420505a691bd4994a/pr-6315--01-addressed-composer.png)

### Open mention menu

The @ ingress opens the existing mention menu and shows which agents are
already addressed.

![Open mention menu with automatically addressed agents
highlighted](https://raw.githubusercontent.com/block/buzz/74c2cbbd80ed630a0c6e00c420505a691bd4994a/pr-6315--02-open-mention-menu.png)

### Mention options

The inline options pane controls whether a successful one-time agent
mention carries into later messages.

![Automatic mention options expanded above the mention
menu](https://raw.githubusercontent.com/block/buzz/74c2cbbd80ed630a0c6e00c420505a691bd4994a/pr-6315--03-mention-options.png)

### Agent settings

The same preference is available in **Settings → Agents →
Conversations**.

![Automatic agent mentions preference in the Agents settings
pane](https://raw.githubusercontent.com/block/buzz/74c2cbbd80ed630a0c6e00c420505a691bd4994a/pr-6315--04-agent-settings.png)

---------

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Rizz <302abe414ca6e3134763d2539bfcf145aea2a63fe5f8455204ed602fd40cf381@buzz.block.builderlab.xyz>
Co-authored-by: Carl <acda9e433d19dcd0e6b6840f7f4b98f3a56f1fab98049d444c087019e6d36560@buzz.block.builderlab.xyz>
## Summary
- add foreground mobile Huddles on Android and iOS with native Opus
capture/playback, mute, speaker routing, participants, lifecycle, and
minimized drawer UI
- keep mobile Huddle cards and roster state live, including ended rooms,
relay-resolved profiles, and agents
- broadcast desktop agent TTS through the existing Huddle audio protocol

## Scope
Foreground human-to-human voice MVP only. Agent setup/transcripts,
background calling, recording, and advanced device controls remain out
of scope.

## Validation
- `just mobile-check`
- `just mobile-test` — 1,500 passed
- `just desktop-check` and `just desktop-test` — 4,957 passed
- desktop typecheck, strict Clippy, and Tauri tests — 2,445 passed, 15
ignored
- mobile worktree identity contract checks
- physical Pixel/iPhone behavior reviewed during development

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Kenny Lopez <klopez4212@gmail.com>
Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Co-authored-by: leader <71e9f2c44a6932b6772caaaccda1911d010463c3e2c6c40410b8329956046801@buzz.block.builderlab.xyz>
Co-authored-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
## Why
The ACP prompt puts a machine-specific Workspace prefix before static
base guidance and labels the user-facing agent instruction layer as the
generic System section. Because the cwd varies by launch and worktree,
leading with it reduces reusable prompt-prefix stability.

`[Workspace]` was added in [PR
block#1194](block#1194) as a defensive fix after
a broken `~/.sprout` → `~/.buzz` migration caused agents to scan `$HOME`
and trigger macOS TCC prompts. This change retains that grounding while
shrinking it to the current working directory and moving dynamic
environment context after the static Base prompt.

## What
- Emit the prompt in Base → Workspace → Agent Instructions order
- Reduce Workspace to `Current working directory: <absolute path>`
- Resolve cwd as an absolute native-platform path and preserve Windows
drive/UNC paths instead of checking for a leading `/`
- Emit Agent Instructions for persona and standalone agent instructions
across modern and legacy ACP paths
- Preserve parsing for archived observer frames that used System or the
former Workspace-before-Base order, and align the persona catalog label

## Risk Assessment
Medium-low — this changes prompt framing for every newly created agent
session. Existing archived observer frames remain parseable, and
execution still uses the same ACP working directory. Cwd resolution now
fails clearly instead of substituting `/` when the process directory
cannot be resolved.

## References
- block#1103
- block#1194

Generated with Codex

---------

Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Diagnostic profiling on a large community (101 issues, 258 PRs) showed
Projects tab switches taking 2.5–3.6s, dominated by single React commits
of 0.5–1.5s and per-render recomputation — fetch work was already off
the main thread; the cost was building the UI.

### Measured: tab click → painted, per tab

| tab | before | after |
|---|---|---:|
| projects | 3,608ms | 320–580ms |
| repositories | 3,126–3,534ms | 310–410ms |
| tasks | 395–1,101ms | ~115ms |
| reviews | 322–2,603ms | ~96ms |
| activity | 597–741ms | ~148ms |

Single-commit ceiling dropped from 1,541ms to ≤200ms (growth steps
25–40ms). Fixes in profiled-cost order:

- **Profile popover body mounts only while open.** `UserProfilePopover`
carried seven query subscriptions plus interaction hooks per instance
even when closed; grids mount hundreds (five per card in people stacks,
one per row author) — measured **~40ms per card**, the dominant share of
the 1.2s card-tab commits. The always-mounted shell is now just the
Radix root + trigger; trigger markup, hover timing, and keyboard
handling are unchanged, and hover/tooltip event continuity is preserved
because the trigger never remounts.
- **Incremental row mounting.** The first 12 cards / 30 rows render in
the first commit; the rest stream in 36–60-per-frame low-priority
transitions. Grouped lists trim across group boundaries via a pure,
tested slicer; the mounted count survives in-place refetches.
- **Activity feed**: was rebuilt unmemoized on every render,
markdown-flattening every issue/PR/comment body in the community just to
sort and keep 30 items (~360+ flattens per render on the measured
community). Now memoized, and bodies stay raw until after the sort+slice
— 30 flattens, once per data change.
- **Contribution graph** (always-visible rail, so every tab paid for
it): ~180 day cells each wrapped in a Radix tooltip with per-cell Intl
date formatting per render. Now memoized, cells precomputed once per
data change, native `title` tooltips. (The activity-bar segments keep
their styled Radix tooltips — pinned by an existing spec.)
- **Rows/cards memoized with identity-stable props**: per-row selection
arrays were rebuilt per row per render (O(n²) — 258 PRs × 258-item
arrays each render) and are now hoisted and shared; people arrays derive
inside the memoized cards; the rail's stat walk over every issue/PR is
memoized.
- **`content-visibility: auto`** on cards and rows so offscreen entries
skip layout and paint; **tab switches run in a React transition** so the
click stays responsive while the new tree mounts.

Remaining known cost (out of scope): cold-entry data readiness — the
work-item and activity queries ship thousands of events to compute
counts (2–4s on a large community; see the fan-lifecycle PR). The
structural fix is a relay-side aggregate; tracked as follow-up.

---------

Signed-off-by: Max Lampert <maxwell@squareup.com>
## Summary

- downgrade Mobile Huddle authentication and native media configuration
from protocol v3 to the currently deployed relay's v2 contract
- restore the released one-byte relay peer prefix while retaining later
reconnect, roster, and playout-reset reliability fixes
- update Android, iOS, protocol documentation, and focused tests
together

Protocol v2 does not carry v3's occupancy epoch on audio frames, so it
cannot fence the narrow delayed-packet/peer-index-reuse race. This is an
intentional compatibility tradeoff until the relay v3 rollout is ready.

### Related issue

None found.

### Testing

- `just mobile-check`
- `just mobile-test` — 1,661 tests passed
- Android debug build installed and launched on Pixel 10 as
`xyz.block.buzz.mobile.sprout_mobile_profile_settings`; foreground
process verified
- signed iOS Release build installed and launched on iPhone as
`com.buzz.buzzMobile`; running process verified

A live two-device Huddle audio call remains a manual verification step.

Signed-off-by: kenny lopez <klopez4212@gmail.com>
## Summary
- arrange Huddle participants in a responsive, equal-weight cluster with
spring enter/exit motion and a `+N` overflow
- spotlight tapped participants over a blurred call surface, with a
roster for hidden participants and no self-avatar action
- add selection haptics across full-screen and drawer controls,
including both end-call buttons
<img width="1080" height="2424" alt="Screenshot_20260819-151448"
src="https://github.com/user-attachments/assets/00b7fdca-2304-4788-9952-e07224798513"
/>
<img width="1080" height="2424" alt="Screenshot_20260819-151422"
src="https://github.com/user-attachments/assets/a0cfc861-0519-44ff-bb56-4c983ed6344c"
/>

## Validation
- `just mobile-check`
- focused participant, drawer-control, and full-screen end-call widget
tests
- Huddle-focused widget suite (15 tests)
- full mobile Flutter suite (1,538 tests)

## Dependency
Built on block#6056 and contains only the follow-up interaction work. Merge
after block#6056 lands.

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Kenny Lopez <klopez4212@gmail.com>
Signed-off-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Co-authored-by: leader <71e9f2c44a6932b6772caaaccda1911d010463c3e2c6c40410b8329956046801@buzz.block.builderlab.xyz>
Co-authored-by: Tom Brow <tomb@block.xyz>
Co-authored-by: Mongo <9cfd347903944d5b85aa6c93d2ab67381b978a92a31914bca69998968752a1d7@buzz.block.builderlab.xyz>
Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
The Aug 8 language and evidence work was lost during a subsequent rebase.
This restores the agreed changes:

- 'Ready locally' → 'Runtime ready' in card and AGENTS.md
- 'Never verified' → 'Not yet observed' for time labels
- 'Sources' → 'Included in session launch' for tool sources label
- Session/channel identity shown in manifest header
- Credential persistence readiness check (Keyring entry found)
- lastVerifiedAt derives only from observer events, not catalog/runtime refreshes

Cherry-picked from work-2957-feedback branch. AGENTS.md conflict resolved
by keeping the rebased base and appending the wolfyy970-agreed guidance.

Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
… per wolfyy970 review

Two truth-in-label changes from wolfyy970's latest review on block#2957:

1. 'Keyring entry verified' → 'Keyring entry found'. The probe only
   confirms an entry exists under the agent's keyring name — it does
   not prove the stored key derives the agent's pubkey. The Rust doc
   comment already says this; the UI detail now matches.

2. lastVerifiedAt now derives only from observer events (initialize,
   session_config_captured, available_commands_update). Previously it
   included catalogObservedAt and runtimeObservedAt, so a catalog or
   runtime query refresh could make the card say 'Verified just now'
   without any new session evidence. The label now reflects only
   actual session observation.

Added a test verifying lastVerifiedAt ignores catalog/runtime refreshes.

Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
…d event

The reduceAgentCapabilityEvidence call was using an undefined 'event'
variable left over from a loop refactor on main. Changed to iterate
over all sortedAdded events so capability evidence is accumulated
correctly.

Co-authored-by: Brad Groux <brad@digitalmeld.com>
Signed-off-by: Brad Groux <brad@digitalmeld.com>
The observer store trims to OBSERVER_EVENTS_LOW_WATER (90% of
MAX_OBSERVER_EVENTS = 2700) when events exceed the 3000 cap, not to
the cap itself. Updated the test assertion and added a comment
explaining the low-water mark.

Co-authored-by: Brad Groux <brad@digitalmeld.com>
Signed-off-by: Brad Groux <brad@digitalmeld.com>
BradGroux added a commit to BradGroux/buzz that referenced this pull request Aug 23, 2026
… per wolfyy970 review

Two truth-in-label changes from wolfyy970's latest review on block#2957:

1. 'Keyring entry verified' → 'Keyring entry found'. The probe only
   confirms an entry exists under the agent's keyring name — it does
   not prove the stored key derives the agent's pubkey. The Rust doc
   comment already says this; the UI detail now matches.

2. lastVerifiedAt now derives only from observer events (initialize,
   session_config_captured, available_commands_update). Previously it
   included catalogObservedAt and runtimeObservedAt, so a catalog or
   runtime query refresh could make the card say 'Verified just now'
   without any new session evidence. The label now reflects only
   actual session observation.

Added a test verifying lastVerifiedAt ignores catalog/runtime refreshes.

Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
@BradGroux
BradGroux force-pushed the agent/agent-capability-readiness branch from 936c17a to 7ae9279 Compare August 23, 2026 02:05
@BradGroux

Copy link
Copy Markdown
Contributor Author

Rebased onto latest main (e23632941). One conflict resolved in desktop/src/features/agents/AGENTS.md.

Main's #6338 rewrote rule 12 (owner-only builds) with expanded scope covering relay-agent mentions. The PR's rule 15 (capability manifests) is kept as a separate rule above main's updated rule 12, preserving both the capability manifest guidance and main's broader owner-only mention policy. The PR's old version of rule 12 (same-owner discovery only) is dropped in favor of main's more complete version.

cargo check -p buzz-acp clean.

@BradGroux BradGroux closed this Aug 23, 2026
@BradGroux
BradGroux force-pushed the agent/agent-capability-readiness branch from 7ae9279 to df54ed0 Compare August 23, 2026 18:24
BradGroux added a commit to BradGroux/buzz that referenced this pull request Aug 24, 2026
… per wolfyy970 review

Two truth-in-label changes from wolfyy970's latest review on block#2957:

1. 'Keyring entry verified' → 'Keyring entry found'. The probe only
   confirms an entry exists under the agent's keyring name — it does
   not prove the stored key derives the agent's pubkey. The Rust doc
   comment already says this; the UI detail now matches.

2. lastVerifiedAt now derives only from observer events (initialize,
   session_config_captured, available_commands_update). Previously it
   included catalogObservedAt and runtimeObservedAt, so a catalog or
   runtime query refresh could make the card say 'Verified just now'
   without any new session evidence. The label now reflects only
   actual session observation.

Added a test verifying lastVerifiedAt ignores catalog/runtime refreshes.

Co-authored-by: Brad Groux <bradgroux@hotmail.com>
Signed-off-by: Brad Groux <bradgroux@hotmail.com>
@BradGroux

Copy link
Copy Markdown
Contributor Author

This PR was accidentally closed when branches were force-pushed after a commit identity rewrite. The changes have been re-created as #6643 with the same commits rebased onto the latest main. Review history and comments from this PR are preserved here for reference.

#6643

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show what each agent can do and whether it is ready before delegation