Skip to content

fix: agent rename restart, avatar fallback, migration immutability - #2507

Open
Chessing234 wants to merge 4 commits into
block:mainfrom
Chessing234:fix/rename-avatar-migrations
Open

Chessing234 wants to merge 4 commits into
block:mainfrom
Chessing234:fix/rename-avatar-migrations

Conversation

@Chessing234

Copy link
Copy Markdown
Contributor

Summary

  • Renames trip restart + refresh the agents UI (#1823)
  • Standalone agent cards fall back to the managed avatar URL (#2366)
  • CI rejects in-place edits to shipped migrations (#2472)

Test plan

  • Rename a running agent → restart required / auto-restart; Agents list shows new name
  • Custom agent with avatar but empty profile picture still shows icon in Agents
  • PR that edits an existing migrations/*.sql fails the new CI check; adding a new migration passes

Closes #1823
Closes #2366
Closes #2472

Made with Cursor

@Chessing234
Chessing234 requested a review from a team as a code owner July 23, 2026 12:21
wpfleger96 added a commit that referenced this pull request Jul 27, 2026
…propagates (#2607)

## Problem

Part of #2423 (renaming personal agents desynchronises identity).

Renaming an agent definition (persona) propagates the new display name
to its
linked agent instances (`propagate_persona_name_rename` in
`desktop/src-tauri/src/commands/personas/mod.rs`) and saves
`managed-agents.json` — but, unlike the instance-rename path
(`update_managed_agent`), it never re-retains the renamed instances'
kind:30177
managed-agent identity records. `record.name` is part of the published
identity
projection (`agent_event_content`), so after a persona rename:

- `managed-agents.json` says the NEW name,
- the retained kind:30177 row (retention.db → relay flush loop) still
carries
  the OLD name, with the OLD `created_at`.

The stale identity record stays live on the relay until the next app
launch,
when the boot-time reconcile (`reconcile_agents_in_dir`) finally notices
the
content diff and republishes. Until that restart, any surface that
resolves
agents from kind:30177 records (second desktop of the same owner, CLI,
other
NIP-AP clients) sees the OLD name bound to the agent pubkey while the
kind:0
profile already shows the NEW one — the name→identity binding desync
described
in #2423, and consistent with the report's observation that repairing
state
required "a separate restart".

## Fix

- Extract the per-record retain body of the boot reconcile into
`managed_agents::reconcile::retain_agent_record(conn, keys, record) ->
Result<bool, String>`
— one shared content-diff + monotonic-`created_at`-bump engine (returns
whether a row was rewritten). `reconcile_agents_in_dir` now calls it per
  record (behavior unchanged; existing reconcile tests still pass).
- `commands::agents::retain_managed_agent_pending` delegates to the
shared
  engine instead of carrying a duplicate implementation (same semantics:
  projection-equality no-op guard, monotonic bump, `pending_sync = 1`).
- `update_persona` (Phase 1, still under the store lock, after
`save_managed_agents`): call `retain_managed_agent_pending` for every
record
the rename propagated to — mirroring `update_managed_agent`. Avatar-only
edits are deliberately excluded (the avatar is not part of the
kind:30177
  projection; retaining would be a guaranteed no-op).

No new events, kinds, or APIs — this uses the existing signed-event
retention
and flush pipeline, per CONTRIBUTING's guidance to prefer a signed Nostr
event
and the existing ingest path over endpoint-specific JSON APIs.

## Out of scope (deliberately)

- Rename → runtime restart is #1823, fixed by open PR #2507
(spawn_hash).
- Surfacing kind:0 relay profile-sync failures on rename is PR
#2302/#2279
  territory (and largely superseded by the merged rollback in #2258).
- Mention-picker UX (owner/status disambiguation) and channel-membership
repair for stale identities: TS-side, noted in #2423, not touched here.

## Test evidence

Two new unit tests in
`desktop/src-tauri/src/managed_agents/reconcile/tests.rs`
(same harness as the existing reconcile tests — tempdir + retention.db +
fresh
keys, no AppHandle):

- `rename_re_retains_identity_record_with_new_name` — retain "Fizz",
confirm
  flush, rename to "Spark", re-retain: row keeps the pubkey coordinate,
  carries the new name only, is `pending_sync`, and its `created_at` is
  strictly past the retained head (replaceable-event acceptance).
- `retain_agent_record_is_noop_when_unchanged` — an unchanged projection
does
  not rewrite the row and produces zero `pending_sync` churn.

Ran scoped per CONTRIBUTING build discipline (from `desktop/src-tauri`):

```
cargo fmt -p buzz-desktop                                  # applied, clean
cargo clippy -p buzz-desktop --lib --tests -- -D warnings  # exit 0, no warnings
cargo test -p buzz-desktop --lib                           # full lib suite
```

Full `buzz-desktop` lib suite: **1562 passed, 0 failed, 13 ignored** —
including all 12 `managed_agents::reconcile` tests (10 pre-existing, all
unmodified in behavior, plus the 2 new regression tests above).

## Links

- Issue: #2423
- Adjacent (no overlap): PR #2507 (rename-restart, #1823), PRs
#2302/#2279
(kind:0 sync-failure surfacing), merged #2258 (instance-rename
rollback).

---------

Signed-off-by: Sean Gearin <sgearin@gmail.com>
Co-authored-by: Sean Gearin <sgearin@gmail.com>
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Include the display name in the spawn config hash and refresh the agents UI after instance updates so renames apply to AGENTS.md and mid-session identity.

Signed-off-by: Taksh <takshkothari09@gmail.com>

Signed-off-by: Taksh <takshkothari09@gmail.com>
Prefer the managed agent avatar URL when the Nostr profile picture is missing so custom agents do not look stopped across communities.

Signed-off-by: Taksh <takshkothari09@gmail.com>

Signed-off-by: Taksh <takshkothari09@gmail.com>
Fail PRs that modify shipped migrations so sqlx checksums stay valid on upgrade.

Signed-off-by: Taksh <takshkothari09@gmail.com>

Signed-off-by: Taksh <takshkothari09@gmail.com>
@Chessing234
Chessing234 force-pushed the fix/rename-avatar-migrations branch from c800f48 to aa2df5e Compare July 29, 2026 15:00
@Chessing234

Copy link
Copy Markdown
Contributor Author

@tlongwell-block @wesbillman @wpfleger96 mind taking a look when you get a chance?

calvadev pushed a commit to shopstr-eng/buzz that referenced this pull request Aug 3, 2026
…propagates (block#2607)

## Problem

Part of block#2423 (renaming personal agents desynchronises identity).

Renaming an agent definition (persona) propagates the new display name
to its
linked agent instances (`propagate_persona_name_rename` in
`desktop/src-tauri/src/commands/personas/mod.rs`) and saves
`managed-agents.json` — but, unlike the instance-rename path
(`update_managed_agent`), it never re-retains the renamed instances'
kind:30177
managed-agent identity records. `record.name` is part of the published
identity
projection (`agent_event_content`), so after a persona rename:

- `managed-agents.json` says the NEW name,
- the retained kind:30177 row (retention.db → relay flush loop) still
carries
  the OLD name, with the OLD `created_at`.

The stale identity record stays live on the relay until the next app
launch,
when the boot-time reconcile (`reconcile_agents_in_dir`) finally notices
the
content diff and republishes. Until that restart, any surface that
resolves
agents from kind:30177 records (second desktop of the same owner, CLI,
other
NIP-AP clients) sees the OLD name bound to the agent pubkey while the
kind:0
profile already shows the NEW one — the name→identity binding desync
described
in block#2423, and consistent with the report's observation that repairing
state
required "a separate restart".

## Fix

- Extract the per-record retain body of the boot reconcile into
`managed_agents::reconcile::retain_agent_record(conn, keys, record) ->
Result<bool, String>`
— one shared content-diff + monotonic-`created_at`-bump engine (returns
whether a row was rewritten). `reconcile_agents_in_dir` now calls it per
  record (behavior unchanged; existing reconcile tests still pass).
- `commands::agents::retain_managed_agent_pending` delegates to the
shared
  engine instead of carrying a duplicate implementation (same semantics:
  projection-equality no-op guard, monotonic bump, `pending_sync = 1`).
- `update_persona` (Phase 1, still under the store lock, after
`save_managed_agents`): call `retain_managed_agent_pending` for every
record
the rename propagated to — mirroring `update_managed_agent`. Avatar-only
edits are deliberately excluded (the avatar is not part of the
kind:30177
  projection; retaining would be a guaranteed no-op).

No new events, kinds, or APIs — this uses the existing signed-event
retention
and flush pipeline, per CONTRIBUTING's guidance to prefer a signed Nostr
event
and the existing ingest path over endpoint-specific JSON APIs.

## Out of scope (deliberately)

- Rename → runtime restart is block#1823, fixed by open PR block#2507
(spawn_hash).
- Surfacing kind:0 relay profile-sync failures on rename is PR
block#2302/block#2279
  territory (and largely superseded by the merged rollback in block#2258).
- Mention-picker UX (owner/status disambiguation) and channel-membership
repair for stale identities: TS-side, noted in block#2423, not touched here.

## Test evidence

Two new unit tests in
`desktop/src-tauri/src/managed_agents/reconcile/tests.rs`
(same harness as the existing reconcile tests — tempdir + retention.db +
fresh
keys, no AppHandle):

- `rename_re_retains_identity_record_with_new_name` — retain "Fizz",
confirm
  flush, rename to "Spark", re-retain: row keeps the pubkey coordinate,
  carries the new name only, is `pending_sync`, and its `created_at` is
  strictly past the retained head (replaceable-event acceptance).
- `retain_agent_record_is_noop_when_unchanged` — an unchanged projection
does
  not rewrite the row and produces zero `pending_sync` churn.

Ran scoped per CONTRIBUTING build discipline (from `desktop/src-tauri`):

```
cargo fmt -p buzz-desktop                                  # applied, clean
cargo clippy -p buzz-desktop --lib --tests -- -D warnings  # exit 0, no warnings
cargo test -p buzz-desktop --lib                           # full lib suite
```

Full `buzz-desktop` lib suite: **1562 passed, 0 failed, 13 ignored** —
including all 12 `managed_agents::reconcile` tests (10 pre-existing, all
unmodified in behavior, plus the 2 new regression tests above).

## Links

- Issue: block#2423
- Adjacent (no overlap): PR block#2507 (rename-restart, block#1823), PRs
block#2302/block#2279
(kind:0 sync-failure surfacing), merged block#2258 (instance-rename
rollback).

---------

Signed-off-by: Sean Gearin <sgearin@gmail.com>
Co-authored-by: Sean Gearin <sgearin@gmail.com>
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
@Chessing234
Chessing234 force-pushed the fix/rename-avatar-migrations branch from aa2df5e to 8a96132 Compare August 5, 2026 10:38
BradGroux pushed a commit to BradGroux/buzz that referenced this pull request Aug 23, 2026
…propagates (block#2607)

## Problem

Part of block#2423 (renaming personal agents desynchronises identity).

Renaming an agent definition (persona) propagates the new display name
to its
linked agent instances (`propagate_persona_name_rename` in
`desktop/src-tauri/src/commands/personas/mod.rs`) and saves
`managed-agents.json` — but, unlike the instance-rename path
(`update_managed_agent`), it never re-retains the renamed instances'
kind:30177
managed-agent identity records. `record.name` is part of the published
identity
projection (`agent_event_content`), so after a persona rename:

- `managed-agents.json` says the NEW name,
- the retained kind:30177 row (retention.db → relay flush loop) still
carries
  the OLD name, with the OLD `created_at`.

The stale identity record stays live on the relay until the next app
launch,
when the boot-time reconcile (`reconcile_agents_in_dir`) finally notices
the
content diff and republishes. Until that restart, any surface that
resolves
agents from kind:30177 records (second desktop of the same owner, CLI,
other
NIP-AP clients) sees the OLD name bound to the agent pubkey while the
kind:0
profile already shows the NEW one — the name→identity binding desync
described
in block#2423, and consistent with the report's observation that repairing
state
required "a separate restart".

## Fix

- Extract the per-record retain body of the boot reconcile into
`managed_agents::reconcile::retain_agent_record(conn, keys, record) ->
Result<bool, String>`
— one shared content-diff + monotonic-`created_at`-bump engine (returns
whether a row was rewritten). `reconcile_agents_in_dir` now calls it per
  record (behavior unchanged; existing reconcile tests still pass).
- `commands::agents::retain_managed_agent_pending` delegates to the
shared
  engine instead of carrying a duplicate implementation (same semantics:
  projection-equality no-op guard, monotonic bump, `pending_sync = 1`).
- `update_persona` (Phase 1, still under the store lock, after
`save_managed_agents`): call `retain_managed_agent_pending` for every
record
the rename propagated to — mirroring `update_managed_agent`. Avatar-only
edits are deliberately excluded (the avatar is not part of the
kind:30177
  projection; retaining would be a guaranteed no-op).

No new events, kinds, or APIs — this uses the existing signed-event
retention
and flush pipeline, per CONTRIBUTING's guidance to prefer a signed Nostr
event
and the existing ingest path over endpoint-specific JSON APIs.

## Out of scope (deliberately)

- Rename → runtime restart is block#1823, fixed by open PR block#2507
(spawn_hash).
- Surfacing kind:0 relay profile-sync failures on rename is PR
block#2302/block#2279
  territory (and largely superseded by the merged rollback in block#2258).
- Mention-picker UX (owner/status disambiguation) and channel-membership
repair for stale identities: TS-side, noted in block#2423, not touched here.

## Test evidence

Two new unit tests in
`desktop/src-tauri/src/managed_agents/reconcile/tests.rs`
(same harness as the existing reconcile tests — tempdir + retention.db +
fresh
keys, no AppHandle):

- `rename_re_retains_identity_record_with_new_name` — retain "Fizz",
confirm
  flush, rename to "Spark", re-retain: row keeps the pubkey coordinate,
  carries the new name only, is `pending_sync`, and its `created_at` is
  strictly past the retained head (replaceable-event acceptance).
- `retain_agent_record_is_noop_when_unchanged` — an unchanged projection
does
  not rewrite the row and produces zero `pending_sync` churn.

Ran scoped per CONTRIBUTING build discipline (from `desktop/src-tauri`):

```
cargo fmt -p buzz-desktop                                  # applied, clean
cargo clippy -p buzz-desktop --lib --tests -- -D warnings  # exit 0, no warnings
cargo test -p buzz-desktop --lib                           # full lib suite
```

Full `buzz-desktop` lib suite: **1562 passed, 0 failed, 13 ignored** —
including all 12 `managed_agents::reconcile` tests (10 pre-existing, all
unmodified in behavior, plus the 2 new regression tests above).

## Links

- Issue: block#2423
- Adjacent (no overlap): PR block#2507 (rename-restart, block#1823), PRs
block#2302/block#2279
(kind:0 sync-failure surfacing), merged block#2258 (instance-rename
rollback).

---------

Signed-off-by: Sean Gearin <sgearin@gmail.com>
Co-authored-by: Sean Gearin <sgearin@gmail.com>
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Taksh <takshkothari09@gmail.com>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 114dbf745f1fe0bdbecb70e07a07f03c23687bdc...64bbff3f89009302df34d7028d8113b7c9f596bb.
A new review must complete for this exact range. When manual authorization
is required, a Block organization member must comment exactly
@buzz-security-review 64bbff3f89009302df34d7028d8113b7c9f596bb to authorize a new review.
Any previous review applies only to its recorded range.

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

Labels

None yet

Projects

None yet

1 participant