## Summary
- remove synthetic preview runtime and configuration data so profiles
show only real agent content
- simplify model settings to the effective values and restore bare
section icons
- make owned-agent profiles resolve to the same current persona instance
from every entry point
## Why
Agent profiles opened from DMs or channels could fall back to a partial
declared-owner view instead of the full managed-agent profile shown on
the Agents page. Test preview content and configuration provenance also
remained visible after the redesign.
## User impact
Owned agent profiles now expose the same actions, runtime, channels,
memories, and configuration regardless of where they are opened.
Profiles no longer synthesize preview data, and model settings use the
same simple title/value hierarchy as the rest of the panel.
## Validation
- `pnpm --dir desktop check`
- `pnpm --dir desktop build:e2e`
- focused unit tests: 10 passed
- profile entry-point integration tests: 2 passed
- configuration screenshot suite: 7 passed, with six visually distinct
captures
Snapshots are attached in a PR comment.
---------
Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Watcher <bb7abfd757d0af7b66569d02ab9c0316b616f9d0c151ecf5b964344c462e7f8f@buzz.block.builderlab.xyz>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Watcher <bb7abfd757d0af7b66569d02ab9c0316b616f9d0c151ecf5b964344c462e7f8f@buzz.block.builderlab.xyz>
## Summary
- render shared-agent instructions as literal text so Markdown cannot
conceal spoiler contents, link destinations, or image sources
- reject non-reviewable Unicode controls at every agent-definition
boundary while preserving legitimate rendered emoji sequences
- verify shared catalog event IDs and signatures before trusting
authorship, coordinates, pagination, or executable content
- preserve the exact system-prompt bytes between review and execution
instead of silently stripping or normalizing content
## Security rationale
Shared system prompts are executable configuration. Previously, catalog
prompts were projected through the chat Markdown renderer, which could
hide text, replace link destinations with benign labels, and turn image
syntax into remote loads. Zero-width and bidirectional controls could
also make reviewed text differ from what the agent executes.
This change establishes a review invariant: the prompt a user sees is
the prompt the agent executes. Definitions that cannot be reviewed
faithfully are rejected rather than rewritten. Catalog events must also
pass Nostr ID/signature verification before they can claim a publisher,
coordinate, or cursor.
## What changed
- catalog instructions render as exact literal text rather than rich
Markdown
- catalog relay events are verified on a fresh wire-shaped object before
paging, coordinate selection, attribution, or projection
- forged content, pubkeys, signatures, and invalid newer heads are
ignored and cannot shadow a valid signed definition
- TypeScript catalog parsing rejects unsafe remote definitions before
they reach the UI
- shared Rust validation covers persona create/update/import, inbound
relay sync, definition-less managed-agent sync, and catalog publication
paths
- definition-less managed agents now fail closed on local create, local
update, and publication before persistence or relay retention
- linked managed agents validate their local name while treating the
persona definition as authoritative; their inert record-level prompt is
not executed or published
- names reject layout controls; prompts retain ordinary newlines and
tabs
- legitimate emoji composition is supported, including contextual VS16,
ZWJ, skin-tone, family, flag, and keycap sequences
- detached selectors/joiners, bidirectional controls, tag characters,
zero-width concealment, and other default-ignorables remain rejected
- names are bounded to 128 characters and prompts to 64 KiB
- contributor guidance documents the byte-for-byte review requirement
for future sharing paths
Validation reports the offending code point and never silently removes
it.
## E2E recording
[buzz-shared-agent-security-e2e.webm](https://github.com/user-attachments/assets/44d6b75f-0877-490f-bda4-a716fae3f700)
The recording demonstrates:
- a safe definition remains visible
- a prompt containing zero-width `U+200B` is rejected
- a name containing bidi override `U+202E` is rejected
- the prompt is preserved exactly
- spoiler, link, and image syntax remains literal and does not render or
load
## Verification
Passed locally:
- `just test`: all 10 unit and Docker-backed integration stages
- desktop frontend unit suite: 4,295 tests
- persona catalog relay unit suite: 32 tests, including forged-event and
cursor-shadowing cases
- focused Rust definition-validation coverage: 3 local create/update
tests and 6 publication-filtered tests
- complete desktop Tauri library suite after rebase: 2,263 passed, 14
ignored, 0 failed
- desktop Tauri clippy with warnings denied and Rust formatting
- complete agent Playwright spec: 34 tests
- the exact formerly failing `inbox-edit` immediate-attachment smoke
test after rebase: 1 test
- focused shared-agent publish, literal-review, hidden-control,
signature, and cross-member import Playwright coverage
- desktop E2E production build and TypeScript typecheck
- changed-file formatting/lint and file-size ratchet
- pre-commit secret scan and DCO signoff
The branch was rebased onto current `main`, which includes the upstream
attachment-button label fix. Fresh post-rebase GitHub CI is green for
every required and selected check: Desktop Core, all four Desktop Smoke
E2E shards, both Desktop E2E Integration shards and their aggregate,
Desktop E2E Relay, Desktop Build (macOS), Windows Rust, Rust Lint, DCO,
security scanners, and Desktop Release Candidate. The previously failing
`Desktop Smoke E2E (3)` shard now passes.
The repository-wide desktop check also reports existing CSS
formatting/`!important` findings in `components.css` and `terminal.css`;
neither file is changed by this PR. GitHub's Desktop Core lint and
format stage passes on the rebased branch.
---------
Signed-off-by: Alex Rosenzweig <arosenzweig@squareup.com>
**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>
## Summary
- replace ambiguous avatar play controls with centered Start and Restart
pills
- preserve avatar clipping while smoothly morphing actions into the
running status dot
- use accessible warning contrast and real restart behavior without a
duplicate status badge
## Validation
- `just ci`
- focused Playwright coverage for morphing, shared geometry, and
light/dark contrast
Signed-off-by: kenny lopez <klopez4212@gmail.com>
The catalog detail pane hardcoded "Community member" for every non-own
catalog entry. The publisher pubkey (`catalogSource.ownerPubkey`) was
already on every entry — it just was not being resolved to a name.
## What changed
**`desktop/src/features/agents/ui/PersonaCatalogDialog.tsx`**
`PersonaCatalogDetail` now calls `useUsersBatchQuery([ownerPubkey])`
when the selected entry is a community (non-own) catalog agent. The
label derivation is extracted into the exported pure function
`resolveCatalogOwnerLabel` and uses truthy fallbacks to handle empty or
whitespace-only kind:0 fields:
- Own entry → `"You"` (unchanged)
- `displayName` present and non-blank → the display name
- `displayName` absent/blank but `name` present and non-blank → the name
- Loading, unresolvable, or both candidates blank → `"Community member"`
(fallback preserved)
The batch query is disabled (`enabled: false`) when the entry is not a
community entry, so there is no extra network call for own entries or
built-in agents.
**`desktop/src/features/agents/ui/personaCatalogOwnerLabel.test.mjs`**
Unit tests for `resolveCatalogOwnerLabel` covering: populated
`displayName` wins; whitespace-only `displayName` falls through to
`name`; both candidates empty/whitespace/null/undefined all fall through
to `"Community member"`.
**`desktop/tests/e2e/agents.spec.ts`**
- Updated the existing assertion — it previously checked for the
hardcoded fallback; now asserts the resolved mock display name
`"alice"`.
- Added "catalog detail shows Community member when the publisher
profile cannot be resolved" — installs a catalog event from an unknown
pubkey and asserts the fallback still renders.
---------
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1g8493u0xfsjrvflg4n08ezd7vec99mnwzlv0qgwpr9d7gvjwhuzqx59rhw <41ea58f1e64c243627e8acde7c89be667052ee6e17d8f021c1195be4324ebf04@buzz.block.builderlab.xyz>
## Summary
- Keep the Agents header full width while cards reflow independently.
- Collapse header actions into an overflow menu at the compact layout
threshold.
- Apply the same responsive grid rules to Agent Teams.
## Validation
- `pnpm -C desktop build:e2e`
- Focused Agents Playwright coverage
- Pre-push desktop checks and unit tests
---------
Signed-off-by: kenny lopez <klopez4212@gmail.com>
## Summary
Fixes two distinct fidelity failures in direct agent sharing:
- The sender now puts the same effective avatar shown on the agent card
into People-share and file-export snapshot PNGs, including
profile/kind:0 fallback avatars.
- The importer now persists the visible PNG body as the portable avatar
instead of ignoring it in favor of sender-local manifest references.
- Export materializes inherited runtime, provider, and model identifiers
verbatim, while preserving explicit definition values. It does not
translate or substitute configuration for a different recipient setup.
- Sharing waits for a profile-only fallback avatar query, preventing an
early-click race.
The PNG import path keeps the existing safety invariant: decode is
capped at 2048×2048 / 32 MiB and re-encoded avatars above the 2 MiB
inline limit fall back to the manifest reference. The exact transparent
1×1 no-avatar placeholder is ignored.
The original Tyler↔Wes screenshot demonstrates both stages: Wren's
attachment had an avatar that disappeared after **Add agent**
(receiver/import failure), while Pinky's attachment was already blank
(sender/projection failure).
### Related issue
N/A — reported and traced in the linked Buzz conversation.
### Testing
- `cargo test --manifest-path desktop/src-tauri/Cargo.toml
commands::personas::snapshot` — 57 passed
- `pnpm exec tsc --noEmit`
- Biome check on changed frontend/E2E files
- Pre-push hooks:
- desktop check
- desktop tests
- desktop Tauri tests — 1853 passed, 14 ignored
- file-size ratchet
The People-share E2E regression asserts that a profile-only avatar
reaches `avatarPngDataUrl` in the real encode command payload.
---------
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
## Why
The agent avatar picker disables Emoji Mart search, making emojis
difficult to find when creating or editing an agent.
## What
- Enable sticky search in the shared agent avatar picker
- Focus the search field when the Emoji tab opens
- Add end-to-end coverage for search, focus, and selection
## Risk Assessment
Low — this is limited to the desktop agent avatar picker and does not
change avatar persistence or agent configuration.
## References
- `pnpm --dir desktop test` — 3,448 passed
- `pnpm --dir desktop typecheck` — passed
- `pnpm --dir desktop exec playwright test tests/e2e/agents.spec.ts` —
20 passed
---
**Update Jul 24, 16:28 EDT:** Completed `CONTRIBUTING.md` validation.
### Manual test
1. Create an agent and open Add avatar → Emoji.
2. Confirm the search field is focused and filters results.
3. Select an emoji and confirm it becomes the avatar.
4. Repeat while editing an existing agent.
### Validation
- `just ci` — passed
- `just test` — passed
### Follow-up work
None.
Generated with Codex