Skip to content

feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock - #3278

Merged
tlongwell-block merged 24 commits into
mainfrom
eva/agent-trading-cards
Aug 1, 2026
Merged

feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock#3278
tlongwell-block merged 24 commits into
mainfrom
eva/agent-trading-cards

Conversation

@tlongwell-block

@tlongwell-block tlongwell-block commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Agent Trading Cards

"Create Agent Card" action in the agent panel that mints an AI-generated trading card PNG which is the agent: the card carries the buzz_agent_snapshot tEXt chunk and is drag-in importable like any snapshot PNG.

What's in here

  • Mint pipeline (Rust): one OpenAI Responses call — gpt-5.6-sol as card designer with gpt-image-2 via the image_generation tool (~2–3 min). New mint_agent_card / save_agent_card commands; preview with reroll; save or send as .agent.png with round-trip verification before any bytes leave the app.
  • Snapshot/chunk work stays in Rust, reusing the existing encoder/decoder seams (byte-compat golden vector proves the plain path is identical to the pre-envelope encoder for placeholder, PNG-injection, and JPEG-transcode paths).
  • Locked cards (NIP-44): optional buzz-agent-snapshot-encrypted envelope encrypted to the (owner, agent) pair. parse_canonical_pubkey performs lift-x curve validation before any API spend; wrong-key decrypt returns a fixed refusal; the plain decoder refuses locked cards.
  • Guardrails: 10 MiB ceiling on final bytes, memory structurally none in the snapshot, full-manifest import disclosure, API-key hygiene via env layering (record > persona > global > process), fail-early validation ordering (all key/lock/NIP-44-cap checks before Responses spend).
  • Import side: full-manifest disclosure dialog, locked-card import disclosure, bounded avatar fetch.

Review

Code reviewed by Wren across the full arc; final locked-card cross-review APPROVED 9/9/9 at exactly this head (64f819dc8), with independent same-SHA verification: Rust lib 1,843/1,843, clippy --all-targets -D warnings, desktop file-size gate.

Live-mint evidence (real API, shipping seams, this SHA)

  • Plain (Honey): 188s, 1500x2250, 5,101,503 bytes (< 10 MiB); decoded manifest == built manifest; memory=none.
  • Locked (Fizz): 176s, 4,670,184 bytes; owner-key and agent-key decrypt both verified via logical manifest compare; wrong-key refusal exact; plain decoder refuses.
  • Live finding: built-in agents' ~171 KB inline avatars exceed the NIP-44 65,535-byte plaintext cap and the fail-early guard fires before API spend — clean error path, noted as a UX follow-up for large-avatar agents choosing lock.

Full evidence (cards + dialog screenshots) posted in the originating thread.

npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d and others added 8 commits July 27, 2026 22:15
…rading Cards

One OpenAI Responses call (designer model + native image_generation tool)
mints a collectible card PNG; the existing agent_snapshot encoder injects
the buzz_agent_snapshot chunk so the card IS an importable .agent.png.

Boundary rules (agreed with Wren):
- Snapshot construction/injection reuses agent_snapshot.rs; no card-only
  wire format.
- Memory exclusion is structural (MemoryLevel::None at build).
- 10 MiB .agent.png ceiling enforced on FINAL bytes post-injection.
- Round-trip verification decodes final bytes and compares the manifest.
- OPENAI_API_KEY resolved via existing env layering (record > persona >
  global > process), never leaves Rust, never logged.
- Card frame template embedded via include_bytes! (generation input only);
  test gate asserts it decodes with the expected shape.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
Review finding (Wren): fetch_avatar buffered the full response before
checking MAX_AVATAR_FETCH_BYTES, so a missing or dishonest Content-Length
could consume unbounded network/memory. Now preflights content_length()
and streams with a running cap check that rejects before appending any
chunk that would cross 10 MiB — same contract as media_download.rs.
Accumulator boundary extracted for unit testing.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
UI lane for Agent Trading Cards: a Sparkles 'Create card' quick action
in the agent panel's primary-action row (gated canManagePersona), opening
AgentCardMintDialog — optional style notes, one long Rust-side mint call
(~2-3 min) with progress copy, preview with reroll, save as .agent.png.
NO_OPENAI_KEY errors point the user at provider settings. tauriPersonas
gains mintAgentCard/saveAgentCard wrappers; no new backend state — reroll
is simply another mint call.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
…are path

Closes the v1 scope gap Wren flagged: the mint dialog only offered Save.
Card preview now includes PersonaShareRecipients + a Send action that
routes through useSnapshotSendController — the exact guarded
encode → upload (uploadMediaBytes) → send pipeline agent snapshots use,
with the same eligibility checkpoints and DM-safety gating. No
card-special relay path, per the kickoff contract.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
…port)

Tyler's encryption requirement, per Wren's wire-contract spec:

- New agent_snapshot_envelope.rs: typed outer envelope
  (format "buzz-agent-snapshot-encrypted", version 1, scheme nip44-v2)
  riding the same allowlisted buzz_agent_snapshot chunk. Plain cards
  keep today's encoder byte-for-byte. NIP-44 v2 conversation key over
  the (owner, agent) pair — both nsecs decrypt, nobody else's.
- Inner caps enforced per NIP-AE's local contract: 65,535-byte
  plaintext cap on the serialized manifest before encryption, envelope
  JSON/ciphertext caps before base64/decrypt work, decrypted UTF-8 cap
  before snapshot parsing.
- Exact-endpoint key resolution only (owner identity key match, or a
  hydrated managed-agent record whose pubkey + derived-secret pubkey
  both equal the embedded agentPubkey) — no trial decryption. All
  unlock failures surface only the constant LOCKED_CARD_REFUSAL.
- mint path: lock flag on mint_agent_card; encrypted round-trip
  verifies by extracting the chunk, decrypting with the same endpoint
  key, and comparing logical manifests (not ciphertext).
- preview/confirm import wired through decode_snapshot_for_import with
  owner keys + loaded records; AgentSnapshotImportPreview gains
  locked: bool (true = unlocked by local keys, full payload disclosed).
- fetch_snapshot_bytes validates locked envelopes structurally in
  transit without decrypting.
- Test vectors per Wren's list: owner/agent unlock, unrelated-key
  refusal, tampered ciphertext, swapped/malformed pubkeys, unknown
  format/version/scheme, plaintext + ciphertext caps, encrypted
  final-PNG round trip, plain-card bytes unchanged.
- File-size gate: inline test modules split to sibling #[path] files
  (agent_snapshot_tests.rs, snapshot/tests_locked.rs) following the
  storage_tests.rs precedent; no new size-gate exceptions.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
…sure

UI half of the optional locked-card feature:

- AgentCardMintDialog: Lock switch (canLock-gated — enabled only when
  the persona has a linked agent instance/pubkey; disabled with a
  'start this agent once' explanation for bare definitions, per Wren's
  discoverability preference), locked-specific post-mint copy.
- UserProfilePanel: canLock = Boolean(managedAgent?.pubkey) threaded
  into the mint target.
- tauriPersonas: mintAgentCard(id, styleNotes?, lock?); MintedAgentCard
  and AgentSnapshotImportPreview gain locked.
- AgentSnapshotImportDialog: locked-card provenance notice rendered
  only when preview.locked (unlocked by local keys, full decrypted
  payload disclosed as usual) + rendering test.
- e2eBridge preview mock updated with the new preview fields.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
…-byte compat vector

Closes both findings from Wren's cross-review at 4434d39:

1. parse_canonical_pubkey now requires PublicKey::xonly() to succeed —
   nostr 0.44's from_hex only decodes 32 bytes and defers lift-x
   validation, so a non-point like "f"*64 previously passed structural
   transit/save validation and failed only at unlock. Non-points are
   now rejected structurally, per the agreed wire contract; the
   malformed-pubkeys vector asserts structural rejection instead of
   pinning the deferred-failure behavior. mint_agent_card uses the same
   canonical check on record.pubkey so a non-point fails BEFORE the
   API spend.

2. Added the plain-byte compatibility vector that the review claim
   referenced: plain_encoder_bytes_identical_to_pre_envelope_encoder
   reimplements the pre-refactor encode_snapshot_png body verbatim and
   asserts byte-identical output across all three composition paths —
   placeholder, PNG-avatar (chunk injection ordering), and JPEG
   transcode.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
@tlongwell-block
tlongwell-block requested a review from a team as a code owner July 28, 2026 07:36
…BASE_URL for card mints

Three follow-ups to the Agent Trading Cards mint flow (#3278):

1. Inline OPENAI_API_KEY capture: new card_mint_key_status command
   checks (never returns) whether a key resolves through the existing
   env layering. When none does, the mint dialog swaps to a key-setup
   panel with a cost disclosure, a pointer to platform.openai.com, and
   a pointer to the free Export sharing path. Saving writes the key to
   the global Agent Defaults env — the same single source of truth the
   mint already reads; no second key store. A NO_OPENAI_KEY mint error
   now flips into key-setup mode instead of a dead-end toast.

2. Owner-direction primacy: the direction box explicitly accepts card
   TEXT direction as well as art, and the Responses prompt is
   restructured so the owner's directions override the default
   art-style and copy guidance (but never the fixed frame/layout/
   text-fidelity contract). Dialog placeholder updated to match.

3. OPENAI_BASE_URL override resolved through the same env layering,
   unlocking Azure OpenAI and Responses-speaking proxies; trailing
   slashes normalized.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d and others added 15 commits July 28, 2026 10:10
… paths, no silent restarts

Addresses Wren's review of the card-mint key UX (buzz-agent-trading-cards):

1. Cost disclosure + free alternative now persist in the normal mint form
   (pre-spend), not only the no-key setup panel: a compact cost note above
   the Mint action plus a shared FreeSharePathRow.

2. Both directions are actionable: 'Get a key at platform.openai.com' is a
   real external-link button (openUrl), and the free path is a 'Share
   without card art' action that closes the mint dialog and opens the
   existing snapshot export flow (wired at the UserProfilePanel callsite;
   optional prop so the dialog degrades gracefully elsewhere).

3. Key save no longer restarts running agents: replaced the general
   set_global_agent_config call (which stops/restarts every running local
   agent whose effective env changes, and whose restart counts the dialog
   discarded) with a narrow card_mint_save_openai_key command — validated
   single-key read-modify-write of the latest on-disk config under the
   managed-agents store lock, no restarts. The mint re-reads config per
   call, so no restart is needed; the toast says running agents pick the
   key up on next restart, and the Agent Defaults query cache is
   invalidated so the settings editor stays fresh.

4. Azure claim narrowed in the responses_url doc comment: OPENAI_BASE_URL
   covers Bearer-auth Responses-speaking endpoints/proxies; Azure's URL
   scheme + api-key header would need a real driver.

5. Owner-copy rule acknowledges the 220-character text-box contract:
   over-limit owner text is condensed minimally, keeping words and intent —
   no mutually impossible verbatim-vs-limit instructions. Prompt-contract
   test updated.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
…nu, completion toast, card gallery

Four UX fixes for the mint flow, per channel feedback:

1. Non-blocking mint. Mint state moves out of the dialog into
   `cardMintStore` (useSyncExternalStore module store): the dialog
   dispatches and closes; a "Minting card… (takes a few minutes)"
   spinner chip lives in the composer activity rail while the job
   runs. Multiple concurrent mints each get their own chip.

2. Card download menu. The finished card image carries the same
   right-click context menu inline channel images have
   (`MediaContextMenu`), routed through `save_agent_card` —
   `download_image` is SSRF-pinned to relay /media/ URLs and can't
   serve a local base64 card.

3. Completion flow. The finished chip is clickable; a success toast
   with a "View card" action fires when the mint lands; both open the
   new global `AgentCardViewerDialog` (the preview/share half of the
   old dialog: save, send, reroll). Successful mints are archived
   Rust-side to the app data dir (`agents/cards/`, PNG + JSON sidecar
   + JPEG grid thumb; new `list_agent_cards` / `load_agent_card`
   commands, archive failures never fail a paid mint), and a
   "View minted cards" gallery lists them newest-first — click a tile
   to view/save/share any previous card.

4. Clipped hint text. The 4-line placeholder paragraph no longer
   overflows the 3-row textarea: short placeholder, examples moved to
   a visible hint line below the field.

Store lifecycle is covered by a 9-case unit suite (injected mintFn,
no Tauri); archive file names are shape-validated against dir escape
with a unit test.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
* origin/main:
  fix(desktop): paint community rail full height (#3382)
  fix(acp): disable goose cron scheduler in managed agent children (#3144)
  feat(desktop): add custom harness inline from agent dialogs (#3252)
  chore(compose): remove stale typesense env vars (#3332)
  feat(desktop): refine agent catalog sharing (#2439)
  fix(desktop): keep drafts out of the Inbox All view (#3217)
  docs: restructure DCO guidance into scannable subsection (#3337)
  Unify mobile loading spinners (#3314)
  fix(desktop): restore the inbox icon in the sidebar (#3341)
  fix(desktop): gate codex-acp on a minimum supported version (#3254)
  feat(cli): add users set-status command for NIP-38 profile status (#3253)
  fix(composer): scope multiline block formatting (#3246)
  feat(chart): add relay pod extension points (#3322)
  Refine mobile attachment picking (#3313)
  Polish mobile message and search layouts (#3121)
  Add mobile message image galleries (#3312)

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>

# Conflicts:
#	desktop/src-tauri/src/commands/personas/snapshot/import.rs
#	desktop/src-tauri/src/managed_agents/agent_snapshot.rs
#	desktop/src/features/agents/ui/AgentSnapshotImportDialog.tsx
…mpty state

A rejected list_agent_cards query previously fell through to the
"No cards yet" branch (data coalesced to []), telling someone their
paid, persisted cards did not exist and offering no recovery.

The gallery's view-state selection moves into a pure helper
(agentCardGalleryViewState) where the error-wins ordering is pinned by
tests: rejected queries render an explicit error state that preserves
the failure message and offers a Retry action wired to refetch.

Review finding by Wren on PR #3278.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Introduced in the origin/main merge conflict resolution when
build_agent_snapshot_import_preview gained a Result return; the closure
already returns Result, so the wrapper trips needless_question_mark
under -D warnings on CI.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
* origin/main:
  feat(acp): steer claude-code and codex agents via _session/steering (#3007)
  feat(desktop): apply WebKit rendering workarounds at startup on Linux (#3271)
  fix(desktop): stabilize flaky DM expansion E2E ordering assertions (#2004)
  docs(contributing): document the Linux system libraries just ci requires (#3396)

Signed-off-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Expose the export flow's memory selector (Agent only / Agent + core
memory / Agent + all memories) in the card mint flow, per Tyler's ask
on #3278.

Rust: mint_agent_card gains an optional memory_level (default "none",
parsed by the shared parse_memory_level). Unlike export there is no
caller-supplied memory-source pubkey: the source is always the resolved
instance itself, so cross-agent memory pairing is structurally
impossible, and bare definitions fail with a clear error before any API
spend. The level → entries selection is extracted into a shared pure
helper (memory_entries_from_listing) used by both paths. The fail-early
NIP-44 cap check and round-trip verification now run on the
memory-bearing snapshot unchanged; the cap error hints at reducing
memory when memory contributed. MintedCard and the archive sidecar
record the memory level (legacy sidecars default to none — honest,
since memory exclusion used to be structural).

UI: mint dialog gets the export-pattern selector (Agent-only default)
with an explicit plaintext disclosure when memory is included in an
UNLOCKED card — suppressed when the card is locked, because the locked
envelope encrypts the manifest and the plaintext warning would be
false. The viewer's import disclosure now reflects the card's actual
memory level instead of unconditionally claiming "no memories".

card.rs and snapshot/tests.rs both crossed the 1000-line gate; their
test modules moved to child-module files (card/tests.rs,
tests_memory_entries.rs), same layout as snapshot/tests.rs already
used.

Tests: 5 new Rust (level→entries selection incl. missing-core,
sidecar back-compat default, MintedCard wire casing) and 1 new node
suite case pinning the store's four-arg mintFn forwarding.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
…size gate

main's new base-tree file-size ratchet (#3352) flags UserProfilePanel.tsx
and UserProfilePanelSections.tsx: this branch's card-mint wiring pushed
both past 1000 lines. Move the primary-action button row components to
UserProfilePrimaryActions.tsx and fold the snapshot-export + card-mint
dialogs into UserProfilePersonaDialogs.tsx. No behavior change.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
* origin/main:
  feat: add explicit entry for claude-opus-5 in model config (#2831)
  fix(desktop): clear stale thread new-message pill (#3411)
  fix(ci): ratchet file sizes against the base tree (#3352)
  chore(ci): bump desktop smoke E2E timeout to 30 minutes (#3409)
  release(chart): publish 0.1.7 (#3393)

Signed-off-by: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
Signed-off-by: npub12gtutshhh76rx0jx697f32f9tffd4hhp3hx58fp4x6u4uemkm7sqf8f757 <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
… stale record snapshot

The minter resolved the card's avatar solely from the local
ManagedAgentRecord's avatar_url — a create-time presentation snapshot.
With agent-managed profiles enabled, desktop reconciliation is disabled
and the agent updates its own kind:0 picture, so the record goes stale
and cards mint with the wrong face.

mint_agent_card now queries the agent's kind:0 profile at the effective
workspace relay before avatar resolution; the published picture wins
unless blank (preferred_avatar_url, unit-tested). Definitions have no
keypair/kind:0 and keep the record avatar. A relay error fails the mint
BEFORE the API spend, per the existing fail-early guards.

Because kind:0 pictures are typically relay-hosted and may sit behind
require_media_get_auth, fetch_avatar now accepts an optional Blossom
get-auth header, minted ONLY for same-origin URLs (is_same_origin,
scheme+host+port, fail-closed on parse errors — same contract as
media_download.rs) and with redirects disabled while auth is attached
(redirect-hop guard). Foreign origins fetch unauthenticated as before.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
* origin/main: (29 commits)
  feat(replica): portable heartbeat-token fence with snapshot-local reader routing (#3268)
  fix(git): channel binding tooling + author remediation for unbound repos (#3626)
  feat: configure S3 URL addressing style (#3400)
  feat: add first-class OpenRouter provider support (#1975)
  feat(agent,acp): wire provider total_tokens through NIP-AM publish chain (#3593)
  chore(release): release Buzz Desktop version 0.5.2 (#3624)
  docs: add Linux rendering troubleshooting guide (#3573)
  fix(desktop): discover bun-installed agent CLIs in ~/.bun/bin (#3343)
  feat(tracing): correlate trace IDs in relay logs (#3608)
  chore(ci): bump Linux AppImage build container to ubuntu:24.04 (#3602)
  feat(cli): mirror Desktop mention delivery (#3330)
  fix(desktop): deduplicate relay outage notification (#3579)
  fix(desktop): reconcile thread arrivals at bottom (#3585)
  fix(mobile): keep TLS on relays joined by invite (#3139)
  Improve emoji autocomplete matching (#3571)
  Fix shared agent avatar import profiles (#3578)
  Fix inline raster avatars in agent catalog (#3581)
  revert(acp): remove dead GOOSE_ACP_SCHEDULER_DISABLED env injection (#3576)
  feat(agent): make Gemini and MLflow-route models usable through databricks_v2 (#3569)
  fix(cli): mask credential env values in --help output (#3570)
  ...

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
…face

Unlocked trading cards embed the generated 1500-wide artwork as the PNG
body, so the #3578 body-wins import override captured the whole card and
published it as the imported agent's kind:0 picture, discarding the live
avatar the mint had just resolved.

Two seams:
- Mint: unlocked cards inline the real (downscaled) avatar bytes into
  the manifest's avatarDataUrl; the minter already holds them. Locked
  mints are unchanged — the NIP-44 plaintext cap cannot carry inline
  pixels and locked envelopes never reach the body override.
- Import: the PNG body only wins when the manifest carries no inline
  avatar bytes. Body-wins stays intact for normal snapshot exports
  (whose body IS the avatar); inline manifest bytes are authoritative.

Regression test: mint-shaped unlocked card (1500x2250 body, inline
manifest avatar) imports the source avatar, not the card artwork.

Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
Co-authored-by: Tyler Longwell <tlongwell@block.xyz>
Signed-off-by: Tyler Longwell <tlongwell@block.xyz>
@tlongwell-block
tlongwell-block merged commit eb049dd into main Aug 1, 2026
27 checks passed
@tlongwell-block
tlongwell-block deleted the eva/agent-trading-cards branch August 1, 2026 02:01
kalvinnchau pushed a commit that referenced this pull request Aug 1, 2026
…n-v1

* origin/main:
  fix(mesh): stop restarting a busy or loading shared-compute node (#3909)
  fix(desktop): preserve first huddle speech (#3962)
  feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock (#3278)
  fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999)
  feat(relay): accept kind:30621 multi-repo projects at ingest (#3171)
  fix(release): preserve main in desktop PR body (#3979)
  chore(release): release Buzz Desktop version 0.5.3 (#3972)
  fix(release): require exact-head approval for desktop tags (#3973)
  fix(release): make desktop tagging squash-safe (#3965)
  Revert "chore(release): release Buzz Desktop version 0.5.3" (#3960)
  docs(nips): add single-coordinate manual-unread override layer and verification model to NIP-RS (#2864)
  chore(release): release Buzz Desktop version 0.5.3

Signed-off-by: npub122y0pqkertljmedu303rl0aqrj3w8pvu43t6jxm6875lzg6f2pwqegc3xc <5288f082d91aff2de5bc8be23fbfa01ca2e3859cac57a91b7a3fa9f12349505c@buzz.block.builderlab.xyz>
adrienlacombe added a commit to adrienlacombe/buzz that referenced this pull request Aug 1, 2026
Upstream's desktop/src-tauri/src/lib.rs sits at exactly the 1000-line
file-size ratchet limit (checked as candidateLines > limit, so it passes on
the boundary with zero headroom). The fork's two-line 'mod relay_allowlist;'
block pushed it to 1002, and the 2026-08-01 sync tripped it: upstream's Agent
Trading Cards commit (block#3278) added six command registrations to lib.rs, so
'just desktop-check' failed on a merge that was otherwise clean.

Move the module to relay/allowlist.rs and declare it from relay.rs, which is
already a fork patch site. lib.rs is now line-for-line identical to upstream
in length and carries no fork patch at all, which both clears the ratchet and
removes a permanent conflict site from its sorted module list. relay is the
right home anyway: both callers reach the allowlist through relay concerns.

Bumping MAX_LINES was rejected — AGENTS.md forbids slipping under the guard
rather than fixing the file. Splitting lib.rs is the real fix and belongs
upstream; upstream has no headroom left either, so their next addition to
lib.rs breaks their own CI.

Call sites move to crate::relay::allowlist. All six allowlist tests pass under
relay::allowlist::tests.

Signed-off-by: adrienlacombe <6303520+adrienlacombe@users.noreply.github.com>
tlongwell-block pushed a commit to Kampe/buzz that referenced this pull request Aug 1, 2026
* origin/main: (98 commits)
  docs: note that addressable channel events scope by d, not h (block#4103)
  docs: fix stale kind count, quick-start numbering, and empty Further Reading (block#2613)
  fix(desktop): keep thread-open affordance in archived channels (block#4012)
  docs: add one-click Railway deploy for a hosted relay (block#2733)
  fix(desktop): point Oh My Pi preset at omp.sh (block#3516)
  fix(mesh): stop restarting a busy or loading shared-compute node (block#3909)
  fix(desktop): preserve first huddle speech (block#3962)
  feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock (block#3278)
  fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (block#3999)
  feat(relay): accept kind:30621 multi-repo projects at ingest (block#3171)
  fix(release): preserve main in desktop PR body (block#3979)
  chore(release): release Buzz Desktop version 0.5.3 (block#3972)
  fix(release): require exact-head approval for desktop tags (block#3973)
  fix(release): make desktop tagging squash-safe (block#3965)
  Revert "chore(release): release Buzz Desktop version 0.5.3" (block#3960)
  docs(nips): add single-coordinate manual-unread override layer and verification model to NIP-RS (block#2864)
  chore(release): release Buzz Desktop version 0.5.3
  fix(release): make immutable desktop release operable (block#3943)
  feat(desktop): import local Pocket voices (block#3259)
  fix(desktop): open profiles from avatars (block#3751)
  ...

Signed-off-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@buzz.block.builderlab.xyz>
tellaho added a commit that referenced this pull request Aug 1, 2026
* origin/main: (24 commits)
  perf(relay): serve relay-membership checks from the read replica (#4124)
  chore(deps): bump nostr-relay-pool for RUSTSEC-2026-0224 (#4139)
  docs(nostr): document #h requirement for live reaction subscriptions (#3487)
  docs(chart): fix ArgoCD example for native OCI sources (full artifact repoURL + path) (#3426)
  docs(readme): clarify which release asset to download per platform (#3481)
  fix(relay): allow open relays to set their NIP-11 workspace icon (kind:9033) (#3998)
  docs: note that addressable channel events scope by d, not h (#4103)
  docs: fix stale kind count, quick-start numbering, and empty Further Reading (#2613)
  fix(desktop): keep thread-open affordance in archived channels (#4012)
  docs: add one-click Railway deploy for a hosted relay (#2733)
  fix(desktop): point Oh My Pi preset at omp.sh (#3516)
  fix(mesh): stop restarting a busy or loading shared-compute node (#3909)
  fix(desktop): preserve first huddle speech (#3962)
  feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock (#3278)
  fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999)
  feat(relay): accept kind:30621 multi-repo projects at ingest (#3171)
  fix(release): preserve main in desktop PR body (#3979)
  chore(release): release Buzz Desktop version 0.5.3 (#3972)
  fix(release): require exact-head approval for desktop tags (#3973)
  fix(release): make desktop tagging squash-safe (#3965)
  ...

Signed-off-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
tellaho added a commit that referenced this pull request Aug 1, 2026
…onfig

* origin/main:
  perf(relay): serve relay-membership checks from the read replica (#4124)
  chore(deps): bump nostr-relay-pool for RUSTSEC-2026-0224 (#4139)
  docs(nostr): document #h requirement for live reaction subscriptions (#3487)
  docs(chart): fix ArgoCD example for native OCI sources (full artifact repoURL + path) (#3426)
  docs(readme): clarify which release asset to download per platform (#3481)
  fix(relay): allow open relays to set their NIP-11 workspace icon (kind:9033) (#3998)
  docs: note that addressable channel events scope by d, not h (#4103)
  docs: fix stale kind count, quick-start numbering, and empty Further Reading (#2613)
  fix(desktop): keep thread-open affordance in archived channels (#4012)
  docs: add one-click Railway deploy for a hosted relay (#2733)
  fix(desktop): point Oh My Pi preset at omp.sh (#3516)
  fix(mesh): stop restarting a busy or loading shared-compute node (#3909)
  fix(desktop): preserve first huddle speech (#3962)
  feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock (#3278)
  fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999)
  feat(relay): accept kind:30621 multi-repo projects at ingest (#3171)
  fix(release): preserve main in desktop PR body (#3979)
  chore(release): release Buzz Desktop version 0.5.3 (#3972)
  fix(release): require exact-head approval for desktop tags (#3973)
  fix(release): make desktop tagging squash-safe (#3965)

Signed-off-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
tellaho added a commit that referenced this pull request Aug 2, 2026
- Incorporate upstream desktop changes required by the pre-push overlap guard
- Preserve the link preview thumbnail stabilization work on the updated base

Co-authored-by: Taylor Ho <taylorkmho@gmail.com>

* origin/main: (26 commits)
  docs: formal spec for remote agents and their management (#3748)
  fix(nip-oa): accept raw Nostr tag form in parse_json_array (#4203)
  perf(relay): serve relay-membership checks from the read replica (#4124)
  chore(deps): bump nostr-relay-pool for RUSTSEC-2026-0224 (#4139)
  docs(nostr): document #h requirement for live reaction subscriptions (#3487)
  docs(chart): fix ArgoCD example for native OCI sources (full artifact repoURL + path) (#3426)
  docs(readme): clarify which release asset to download per platform (#3481)
  fix(relay): allow open relays to set their NIP-11 workspace icon (kind:9033) (#3998)
  docs: note that addressable channel events scope by d, not h (#4103)
  docs: fix stale kind count, quick-start numbering, and empty Further Reading (#2613)
  fix(desktop): keep thread-open affordance in archived channels (#4012)
  docs: add one-click Railway deploy for a hosted relay (#2733)
  fix(desktop): point Oh My Pi preset at omp.sh (#3516)
  fix(mesh): stop restarting a busy or loading shared-compute node (#3909)
  fix(desktop): preserve first huddle speech (#3962)
  feat(desktop): Agent Trading Cards — mintable agent-snapshot card PNGs with optional NIP-44 lock (#3278)
  fix(buzz-acp): thread cache-read tokens into NIP-AM kind:44200 events (#3999)
  feat(relay): accept kind:30621 multi-repo projects at ingest (#3171)
  fix(release): preserve main in desktop PR body (#3979)
  chore(release): release Buzz Desktop version 0.5.3 (#3972)
  ...

Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
wpfleger96 added a commit that referenced this pull request Aug 2, 2026
…from main drift

New ManagedAgentRecord struct literals introduced by #3278 (Agent Trading
Cards) and its companion snapshot-test extraction lacked the
resume_on_restart field added by this branch. Add resume_on_restart: true
(matching the serde default) to both sites.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
tlongwell-block added a commit that referenced this pull request Aug 14, 2026
## Problem

PR #5574's profile-panel redesign dropped `ProfileSummaryView`'s
`onCreateCard` prop — the only caller of `setCardMintTarget` — so the
entire Agent Trading Cards feature (#3278) became unreachable from the
GUI while staying fully wired underneath: mint dialog, background job
store, viewer, gallery, composer chip, and the Rust
`mint_agent_card`/`save_agent_card` commands all survive at main. `git
log -S 'setCardMintTarget('` shows exactly two commits: the feature and
the accidental removal.

## Outcome

The mint trigger returns as a management row in the agent profile's Info
tab, directly under **Export agent**, gated `isBot && canManagePersona`
exactly like Duplicate/Export. Target resolution is byte-for-byte the
original logic: prefer the live instance pubkey, fall back to the
persona/definition id, allow locking only when an instance keypair
exists.

## Shape

- `UserProfileAgentManagementRows`: new optional `onCreateCard` row
(Sparkles icon, `user-profile-create-card-row`), placed after Export.
- Prop threaded `UserProfilePanel` → `ProfileSummaryView` →
`ProfileInfoTabContent` → management rows, mirroring `onExportAgent` at
every layer.
- The mint-target state + open callback move into a `useCardMint` hook
in `UserProfilePersonaDialogs` (beside the `CardMintTarget` type it
manages). This keeps `UserProfilePanel.tsx` at 999 lines — the file sits
at the size-ratchet cap and may not grow.

## Validation

- `pnpm check` green (biome, file-size ratchet, px-text,
pubkey-truncation).
- `pnpm typecheck` green.
- Full desktop unit suite: **4888 passed, 0 failed**.
- Profile e2e spec: **32 passed**, including the updated
management-row-order assertion and a new click → mint-dialog-visible →
Escape → closed exercise of the restored row.

Verified at `bff3110a0aeb3d63683eac9ed3e587829f9436da`, one commit atop
main `01f76ec97`.

Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
RossHartmann added a commit to Kiingo/buzz that referenced this pull request Aug 16, 2026
* Projects v3: unify sharing, discussions, and issue ownership (block#5792)

## Summary

Projects v3 makes repository work shareable, discussion-aware, and
easier to scan in one coherent workspace. People can copy canonical
links, reopen the exact workspace tab, understand issue and pull-request
context at a glance, find related channel conversations, and assign or
unassign issues across Desktop and CLI.

- **Unified workspace** — top-level sections sit above repository
controls in one rounded workspace, with navigation positioned close to
the page heading. README and Files retain branch selection; every
section has a labeled icon header, and Issues and Pull Requests expose
creation from a consistent right-aligned action.
- **Repository management** — the repository selector is always
available, including single-repository projects. Its integrated add flow
lets project owners create a repository manually or select an existing
repository without a separate toolbar button.
- **Readable work-item lists** — issue and pull-request rows use
plain-language context instead of opaque metadata. Files, commits,
issues, pull requests, channels, and contributors share consistent row
density and right-aligned timestamps, while deterministic
fallback-avatar colors keep participants distinct on light backgrounds.
Inbox pull-request metadata wraps between complete phrases and truncates
long channel names instead of compressing copy into narrow columns.
- **Reliable entity links** — projects, repositories, issues, pull
requests, and commits have canonical `buzz://` links, preview cards, OS
deep-link routing, and tab-aware navigation. Reopening the same link
re-applies its destination instead of leaving the user on a locally
selected tab.
- **Related conversations** — repository and work-item views surface
channels discussing the current entity, including participants, channel
navigation, message context, and an explicit notice when discovery
reaches its 500-result cap.
- **Reversible issue ownership** — trusted assignment and unassignment
events work across Desktop, Tauri, `buzz-sdk`, and `buzz issues`.
Assignees appear in project views and the assigned inbox, while
authorized users can remove assignments directly from the assignee row.

Assignment state is derived chronologically from labeled Nostr notes.
Issue authors and repository owners may change any assignee; other users
may only assign or unassign themselves. Shared golden fixtures keep
entity-link grammar and validation aligned across TypeScript and Rust.

The branch also updates `webbrowser` to the patched release for
RUSTSEC-2026-0257.

### Related issue

N/A.

### Testing

- [x] `just ci` — formatting, lint, typechecking, unit tests, and builds
passed
- [x] Full pre-push suite — organization, branch-skew, Desktop checks,
typechecking, and tests passed on the latest push
- [x] `cargo test -p buzz-cli` and focused `buzz-sdk` assignment tests
passed
- [x] Focused Tauri recipient-note and 500-result search-limit tests
passed
- [x] Desktop entity-link and issue-assignment unit tests passed
- [x] Playwright smoke coverage passed for assignment, repeated
entity-link navigation, repository create/select flows, section headers
and actions, timestamp alignment, timeline icons, sentence-style
issue/PR metadata, header spacing, avatar contrast, and Inbox metadata
at stacked and side-rail breakpoints
- [ ] Manual staging pass: link round-trips, Channels tab, assignment
flows, and inbox routing

### Screenshots

Pull requests explain who opened the request, where it lives, and which
branch it comes from; fallback avatars remain visually distinct.

![Pull request list with conversational
metadata](https://raw.githubusercontent.com/block/buzz/2a536de86f7e6f79b349d7bc147b2923ff2b817d/pr-5624--05-pr-list-metadata.png)

Issues use the same sentence-style hierarchy while keeping status and
recency easy to scan.

![Issue list with conversational
metadata](https://raw.githubusercontent.com/block/buzz/2a536de86f7e6f79b349d7bc147b2923ff2b817d/pr-5624--06-issue-list-metadata.png)

The wide Inbox detail keeps author, timestamp, and origin context
readable beside its metadata rail.

![Pull request Inbox detail with readable
metadata](https://raw.githubusercontent.com/block/buzz/e65b433e14b97c45365ed7b68ea402ec01d26615/pr-5624--02-pull-request-detail-wide.png)

[View the complete six-state Projects v3 screenshot
set](block#5624 (comment))
and [the compact/wide Inbox
comparison](block#5624 (comment)).


---

> Supersedes block#5624, whose head commit accumulated permanently-queued
required check suites (block-dco-check et al.) that GitHub never
dispatched. History flattened into a single signed-off commit on latest
main; tree verified byte-identical (`git merge-tree`) to merging the
original branch into main.

---------

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

* fix(desktop): restore the agent trading-card mint button (block#5900)

## Problem

PR block#5574's profile-panel redesign dropped `ProfileSummaryView`'s
`onCreateCard` prop — the only caller of `setCardMintTarget` — so the
entire Agent Trading Cards feature (block#3278) became unreachable from the
GUI while staying fully wired underneath: mint dialog, background job
store, viewer, gallery, composer chip, and the Rust
`mint_agent_card`/`save_agent_card` commands all survive at main. `git
log -S 'setCardMintTarget('` shows exactly two commits: the feature and
the accidental removal.

## Outcome

The mint trigger returns as a management row in the agent profile's Info
tab, directly under **Export agent**, gated `isBot && canManagePersona`
exactly like Duplicate/Export. Target resolution is byte-for-byte the
original logic: prefer the live instance pubkey, fall back to the
persona/definition id, allow locking only when an instance keypair
exists.

## Shape

- `UserProfileAgentManagementRows`: new optional `onCreateCard` row
(Sparkles icon, `user-profile-create-card-row`), placed after Export.
- Prop threaded `UserProfilePanel` → `ProfileSummaryView` →
`ProfileInfoTabContent` → management rows, mirroring `onExportAgent` at
every layer.
- The mint-target state + open callback move into a `useCardMint` hook
in `UserProfilePersonaDialogs` (beside the `CardMintTarget` type it
manages). This keeps `UserProfilePanel.tsx` at 999 lines — the file sits
at the size-ratchet cap and may not grow.

## Validation

- `pnpm check` green (biome, file-size ratchet, px-text,
pubkey-truncation).
- `pnpm typecheck` green.
- Full desktop unit suite: **4888 passed, 0 failed**.
- Profile e2e spec: **32 passed**, including the updated
management-row-order assertion and a new click → mint-dialog-visible →
Escape → closed exercise of the restored row.

Verified at `bff3110a0aeb3d63683eac9ed3e587829f9436da`, one commit atop
main `01f76ec97`.

Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>

* fix(ci): read Playwright version without nested shell quoting (block#5910)

## Summary

- replace the nested one-line shell quoting used to read the Playwright
package version
- write the resolved version to `GITHUB_OUTPUT` from a multiline shell
step

## Why

The `desktop-v0.5.12` release smoke job failed before executing tests
because Bash received escaped quotes inside command substitution and
parsed the Node expression as shell syntax.

## Validation

- `bash scripts/test-release-ref-contract.sh`
- isolated execution of the new shell fragment with a fixture
`@playwright/test/package.json`, producing `version=1.58.2`
- `git diff --check`

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

* chore(release): release Buzz Desktop version 0.5.13 (block#5912)

## Buzz Desktop release v0.5.13

- **Frozen main:** `09768100ec3420f0aa7cd278bd00fe0baab5de8d`
- **Reviewed candidate:** `a239e0f6793ac6e88ccf92cc231054090a9753cc`
- **Previous desktop release:** `desktop-v0.5.12`
- **Proposed immutable tag:** `desktop-v0.5.13`

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>

* ci(release): remove desktop smoke gate (block#5914)

## Summary

- remove the GitHub-hosted desktop smoke job from the desktop release
workflow
- remove the smoke result from manifest assembly dependencies and
promotion conditions
- retain the local smoke tooling for future repair and targeted
validation

The first release execution of this gate spent its full 10-minute
Playwright timeout traversing the 10,000-row fixture, then produced a
987 MB diagnostics upload. All signed platform builds succeeded, but the
smoke prevented manifest publication. This restores the previously
established release boundary while the harness is made suitable for CI
separately.

### Testing

- parsed `.github/workflows/release.yml` with Ruby Psych and asserted
the smoke job/dependencies are absent
- `scripts/test-release-ref-contract.sh`
- exact pushed commit passed the repository pre-push hook

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

* chore(release): release Buzz Desktop version 0.5.14 (block#5917)

## Buzz Desktop release v0.5.14

- **Frozen main:** `1b3dbcaaea882eeea90359c1db02e306d2f4f50a`
- **Reviewed candidate:** `391495e7d347d20b67e39e3c240d17ef63c5c2c0`
- **Previous desktop release:** `desktop-v0.5.13`
- **Proposed immutable tag:** `desktop-v0.5.14`

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>

* Polish mobile message threads and composer (block#5645)

## Summary

- refine mobile message metadata, search spacing, and Activity filter
semantics
- add channel-parity Latest navigation and stable tail following to
threads
- synchronize Android composer/keyboard geometry and keep Latest spacing
stable across IME transitions

## Validation

- `bin/just mobile-check`
- `bin/just mobile-test` (1,276 tests)
- Pixel 10 install/launch and channel/thread keyboard, Latest, tail, and
back-navigation review
- signed iPhone install/launch workflow

## Snapshots

See the review snapshots below.

---------

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>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>

* fix(desktop): hide the offcanvas-collapsed sidebar so it stops painting over the community rail (block#5947)

## Summary

Collapsing the sidebar left a phantom copy of it painted over the
community/relay rail — opaquely on flat themes (vesper et al., which
made the rail look *removed*), and as ghost fragments (muted search-box
fill, truncated channel-name tails) on the Buzz themes whose chrome is
intentionally transparent for the gradient.

**Cause:** block#4281 made the app-sidebar layer `overflow-visible` (the
huddle drawer needs to escape it). That removed the ancestor clipping
the offcanvas collapse relied on: the sidebar slides to `left:
-sidebar-width` but kept painting, exactly over the `z-0` rail (`z-10`
sidebar layer).

**Fix:** the offcanvas-collapsed sidebar container is now `invisible` +
`pointer-events-none`, with `visibility` added to the transition list so
the 200 ms slide-out still animates and the flip happens only at the
transition's end. Theme-independent; no per-theme CSS touched; the
huddle drawer's `overflow-visible` is preserved.

## Before / after

Left 420px of the app with the sidebar collapsed. Before = unpatched
`origin/main` @ 69107dc; after = this branch. Same seeded state, same
build pipeline (`build:e2e` between checkouts).

| theme | before (ghost sidebar over the rail) | after (rail clean: A /
B / + visible) |
|---|---|---|
| vesper |
![before-vesper](https://raw.githubusercontent.com/block/buzz/3f98c576e062e51d976940725d84b4e0be7fd53c/pr-5947--before-vesper.png)
|
![after-vesper](https://raw.githubusercontent.com/block/buzz/3f98c576e062e51d976940725d84b4e0be7fd53c/pr-5947--after-vesper.png)
|
| buzz |
![before-buzz](https://raw.githubusercontent.com/block/buzz/3f98c576e062e51d976940725d84b4e0be7fd53c/pr-5947--before-buzz.png)
|
![after-buzz](https://raw.githubusercontent.com/block/buzz/3f98c576e062e51d976940725d84b4e0be7fd53c/pr-5947--after-buzz.png)
|
| buzz-dark |
![before-buzz-dark](https://raw.githubusercontent.com/block/buzz/3f98c576e062e51d976940725d84b4e0be7fd53c/pr-5947--before-buzz-dark.png)
|
![after-buzz-dark](https://raw.githubusercontent.com/block/buzz/3f98c576e062e51d976940725d84b4e0be7fd53c/pr-5947--after-buzz-dark.png)
|

Before shots: ghost `⌘K` search chip + blue active-item pill painted
over the rail column; on vesper the opaque panel hides the rail buttons
entirely. After: the rail's community buttons (A, B) and `+` are visible
and clickable in all three themes.

Reported by Thomas P in #buzz-bugs:
buzz://message?channel=e62570dd-33ad-42c5-b92b-75f2689f9694&id=9ea401ca1d009f555ca4324e136f8d8d8156db2f8afa3ff89fd038d2c16260f7

cc @klopez4212 — this touches the layout your block#4281/block#5478 work shaped;
please confirm it doesn't defeat the huddle drawer or glass intentions.
The change deliberately hides only the *offcanvas-collapsed* container,
nothing in the expanded path.

## Test plan

- [x] New Playwright regression spec `sidebar-offcanvas-rail.spec.ts`
(buzz / buzz-dark / vesper): collapsed sidebar must be `visibility:
hidden` + `pointer-events: none`, community rail stays visible and
interactive. **Fails on unpatched build** (verified), passes with the
fix.
- [x] Full desktop unit suite: 4,954 pass / 0 fail
- [x] `pnpm typecheck`, `pnpm check` (biome + file-size ratchet +
px-text + pubkey-truncation) green
- [x] Before/after screenshots above captured via the e2e harness on
both builds

Signed-off-by: Thomas Petersen <thomasp@squareup.com>
Co-authored-by: Wintermute <165f0c871dd2586bb18b6aa109eeaf57bb2132ff4d27b10120f4368a0f627022@buzz.block.builderlab.xyz>

* ci: refresh Buzz 0.5.14 fork baseline

Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>

* fix(acp): preserve same-turn action ordering

Signed-off-by: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>

---------

Signed-off-by: Thomas Petersen <thomasp@squareup.com>
Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
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: Ross Hartmann <1750494+RossHartmann@users.noreply.github.com>
Co-authored-by: thomaspblock <thomasp@squareup.com>
Co-authored-by: Wintermute <3f1797424fd9ad6653a83665c660517777cd7f8c228c0d5907f49e01537f3ca5@buzz.block.builderlab.xyz>
Co-authored-by: Tyler <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Co-authored-by: Release Automation <release-automation@users.noreply.github.com>
Co-authored-by: klopez4212 <klopez4212@gmail.com>
Co-authored-by: Fast Fizz <2df81cb51f05a9d5387ef24d7b9ecb8fcdfcd1c70ffabc67061c9596e1b5b1c4@buzz.block.builderlab.xyz>
Co-authored-by: Princess Donut <b238ea756dee4d98afa5883fc7f1de61eeabe65bf700e3a5a5a80db5e42e2c2b@buzz.block.builderlab.xyz>
Co-authored-by: Wintermute <165f0c871dd2586bb18b6aa109eeaf57bb2132ff4d27b10120f4368a0f627022@buzz.block.builderlab.xyz>
bhargavms pushed a commit to EWA-Services/buzz that referenced this pull request Aug 18, 2026
## Problem

PR block#5574's profile-panel redesign dropped `ProfileSummaryView`'s
`onCreateCard` prop — the only caller of `setCardMintTarget` — so the
entire Agent Trading Cards feature (block#3278) became unreachable from the
GUI while staying fully wired underneath: mint dialog, background job
store, viewer, gallery, composer chip, and the Rust
`mint_agent_card`/`save_agent_card` commands all survive at main. `git
log -S 'setCardMintTarget('` shows exactly two commits: the feature and
the accidental removal.

## Outcome

The mint trigger returns as a management row in the agent profile's Info
tab, directly under **Export agent**, gated `isBot && canManagePersona`
exactly like Duplicate/Export. Target resolution is byte-for-byte the
original logic: prefer the live instance pubkey, fall back to the
persona/definition id, allow locking only when an instance keypair
exists.

## Shape

- `UserProfileAgentManagementRows`: new optional `onCreateCard` row
(Sparkles icon, `user-profile-create-card-row`), placed after Export.
- Prop threaded `UserProfilePanel` → `ProfileSummaryView` →
`ProfileInfoTabContent` → management rows, mirroring `onExportAgent` at
every layer.
- The mint-target state + open callback move into a `useCardMint` hook
in `UserProfilePersonaDialogs` (beside the `CardMintTarget` type it
manages). This keeps `UserProfilePanel.tsx` at 999 lines — the file sits
at the size-ratchet cap and may not grow.

## Validation

- `pnpm check` green (biome, file-size ratchet, px-text,
pubkey-truncation).
- `pnpm typecheck` green.
- Full desktop unit suite: **4888 passed, 0 failed**.
- Profile e2e spec: **32 passed**, including the updated
management-row-order assertion and a new click → mint-dialog-visible →
Escape → closed exercise of the restored row.

Verified at `bff3110a0aeb3d63683eac9ed3e587829f9436da`, one commit atop
main `01f76ec97`.

Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Signed-off-by: bhargavms <bhargav.m@ewa-services.com>
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.

1 participant