block / block/buzz

Persona rename leaves linked instances on the old relay identity, and the rename guard makes it unrecoverable

Open
#5,705 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

## Summary

In `desktop-v0.5.10`, a persona-linked agent instance can end up with a `name` that differs from its persona's `display_name`. When that happens:

1. The Desktop UI shows the new name and the agent's system prompt uses the new name, so the rename looks successful.
2. The relay identity (kind:0 `display_name`) is republished from `record.name` on **every agent start**, so the published name silently reverts to the old one.
3. `@mention` resolution runs against the relay member list, so mentioning the agent by the name the UI shows fails to resolve and the message is never delivered.
4. **There is no recovery path in the app.** Renaming again cannot fix it, because the propagation helper skips exactly the records that have diverged.

Observed on a real workspace: three builtin-persona agents renamed on 2026-08-10 kept publishing `Fizz` / `Honey` / `Bumble` two days later, while their definitions, prompts and sidebar entries all read `Monkey2` / `Dummy2` / `Goofus2`. Only a hand-edit of `managed-agents.json` fixed it.

## Root cause

### 1. The rename guard makes divergence permanent

[`propagate_persona_name_rename`](https://github.com/block/buzz/blob/desktop-v0.5.10/desktop/src-tauri/src/commands/personas/update.rs#L36-L53) only renames instances whose current `name` equals the persona's **old** `display_name`:

```rust
if record.name != old_display_name {
continue; // pool-named instance — keep its individualised name
}
```

The intent is sound — pool-named instances (`Birch`, `Compass`) should keep their individual names. But the guard is also the only thing standing between a diverged record and repair, and the condition it tests **can never become true again** once `record.name` and `persona.display_name` differ for any reason. Each subsequent rename moves `old_display_name` further away. The record is stranded permanently.

There is no UI to edit a persona-linked instance's `name` directly (same limitation noted for `acp_command` in #5508), so the owner's only fix is editing `managed-agents.json` by hand with the app quit.

### 2. Relay-synced persona renames don't propagate at all

[`apply_inbound_persona`](https://github.com/block/buzz/blob/desktop-v0.5.10/desktop/src-tauri/src/commands/personas/inbound.rs#L342-L364) overwrites `local.display_name` and `local.system_prompt` from an inbound kind:30175 event, but — unlike `update_persona` — never calls `propagate_persona_name_rename` and never touches linked instances:

```rust
local.display_name = inbound.display_name;
local.avatar_url = inbound.avatar_url;
local.system_prompt = inbound.system_prompt;
```

So a rename performed on device A and synced to device B updates B's definition and prompt while B's instance keeps its old `name`. That is a divergence created by sync alone, with no user error involved — and by defect 1, device B can then never repair it through the UI. This looks like the same ownership problem as #5218, seen from the naming side.

### 3. Startup reconciliation actively overwrites any manual correction

`start_managed_agent` builds the reconcile payload straight from the instance record ([agents.rs#L1114-L1123](https://github.com/block/buzz/blob/desktop-v0.5.10/desktop/src-tauri/src/commands/agents.rs#L1114-L1123)):

```rust
let reconcile = ProfileReconcileData {
name: record.name.clone(),
...
```

and [`profile_needs_sync`](https://github.com/block/buzz/blob/desktop-v0.5.10/desktop/src-tauri/src/commands/agents_profile.rs#L167-L180) treats *any* relay name that differs from `record.name` as stale and republishes.

This is correct behaviour given a correct `record.name`, but it means a stale instance name is not merely unpublished — it is re-asserted over a correct relay profile on every single start. An owner who repairs the relay profile out-of-band (`buzz users set-profile --name`) sees the fix silently reverted the next time the agent boots.

## Evidence from the affected workspace

`managed-agents.json`, `desktop-v0.5.10`, macOS 26.6.1. Definition rows carry `pubkey: ""`; instance rows carry the pubkey and `persona_id`.

| persona_id | definition `display_name` | instance `name` | instance `display_name` |
|---|---|---|---|
| `builtin:fizz` | Monkey2 | **Fizz** | *absent* |
| `builtin:honey` | Dummy2 | **Honey** | *absent* |
| `builtin:bumble` | Goofus2 | **Bumble** | *absent* |
| `2c586e69-…` (never renamed) | Mrs Altman | Mrs Altman | — |
| `e3c3724a-…` (never renamed) | PSSOXBot | PSSOXBot | — |
| `216103d5-…` (never renamed) | youngbot | youngbot | — |

The absent instance `display_name` is the diagnostic: `propagate_persona_name_rename` sets `record.name` **and** `record.display_name` together ([update.rs#L50-L51](https://github.com/block/buzz/blob/desktop-v0.5.10/desktop/src-tauri/src/commands/personas/update.rs#L50-L51)). Neither is set on any of the three, so the helper never ran for them — consistent with the guard skipping all three.

`system_prompt` propagated correctly in all six cases (all three renamed agents run prompts that open *"You are Monkey2 / Dummy2 / Goofus2"*), which is why the rename looks complete from inside the app.

Startup republish, three for three:

| agent | last start | relay `display_name` after |
|---|---|---|
| `builtin:fizz` | 2026-08-12 19:04:28Z | `Fizz` — overwrote a manual correction made 2 days earlier |
| `builtin:bumble` | 2026-08-12 21:01:19Z | `Bumble` — same |
| `builtin:honey` | 2026-08-10 20:32:18Z (not restarted since) | `Dummy2` — manual correction survived |

After hand-editing the three instance `name` fields with the app quit, `builtin:fizz` restarted at 2026-08-12 21:28:37Z and the relay profile stayed `Monkey2`.

## Reproduction

Direct repro of defect 1 (no sync required):

1. Create an agent from a persona, then make `record.name` differ from `persona.display_name` by any route — hand-edit, sync, or pool naming.
2. Rename the persona in Desktop.
3. The sidebar and system prompt update; `record.name` does not.
4. Start the agent. The relay kind:0 `display_name` is republished with the old name.
5. Rename again to try to fix it. It still does not propagate — the guard now compares against an even older name.

Repro of defect 2: rename a persona on device A, let the kind:30175 event reach device B, inspect B's `managed-agents.json` — the definition is renamed, the instance is not.

## Likely origin in this case (hypothesis)

The owner migrated to a new laptop and imported their previous setup. A plausible chain that matches every timestamp on disk: the fresh install seeded builtin instances with the code defaults (`Fizz` / `Honey` / `Bumble`, definitions created `16:25:13Z`, instances `16:35:15Z`), an imported/synced definition then set the persona names to the values from the old machine, and the owner's UI rename ~4 hours later (`20:29Z`) compared `record.name = "Fizz"` against an `old_display_name` that was no longer `Fizz` — so the guard skipped it.

I could not confirm which write path ran on 08-10; that state is gone. The two code-level defects above stand on their own regardless of how the initial divergence was introduced.

## Suggested direction

Not prescribing the ownership model — #5328 and #5508 are already circling it — but three things would each have prevented this independently:

- **Distinguish "pool-named" from "diverged" explicitly** rather than inferring it from name equality. If instances recorded whether their name was individualised (pool-drawn/user-set) or inherited from the definition, the guard would be a flag check and inherited names would always follow a rename.
- **Give `apply_inbound_persona` the same propagation as `update_persona`**, so a synced rename cannot create the divergence in the first place.
- **Surface the divergence.** An agent whose published relay identity differs from the name shown in the UI is user-visible breakage — mentions to it fail — and should not be silent. A stale-name badge, or an editable instance name for persona-linked agents, would give owners a recovery path that is not "quit the app and edit JSON".

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.