From e6f545ec8a4da64c4a05ddb3b3127c67efcb14ff Mon Sep 17 00:00:00 2001 From: Taksh Date: Thu, 23 Jul 2026 15:20:46 +0300 Subject: [PATCH 1/3] fix(desktop): restart agents after rename 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 Co-authored-by: Cursor --- desktop/src-tauri/src/commands/agent_models.rs | 6 +++++- desktop/src-tauri/src/managed_agents/spawn_hash.rs | 4 ++++ .../src/managed_agents/spawn_hash/tests.rs | 13 +++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/desktop/src-tauri/src/commands/agent_models.rs b/desktop/src-tauri/src/commands/agent_models.rs index 425eadb5f..51ffbb555 100644 --- a/desktop/src-tauri/src/commands/agent_models.rs +++ b/desktop/src-tauri/src/commands/agent_models.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashSet}; use nostr::Keys; use serde::Deserialize; -use tauri::{AppHandle, State}; +use tauri::{AppHandle, Emitter, State}; use super::agent_model_process::run_agent_models_command; use super::agent_update_rollback::{rollback_failed_agent_update, AgentUpdateRollback}; @@ -970,6 +970,10 @@ pub async fn update_managed_agent( } } + // Persona/team mutate paths emit this so the Agents UI refreshes; do the + // same after instance edits (rename, respond-to, prompt, …). + let _ = app.emit("agents-data-changed", ()); + Ok(UpdateManagedAgentResponse { agent: summary, profile_sync_error: None, diff --git a/desktop/src-tauri/src/managed_agents/spawn_hash.rs b/desktop/src-tauri/src/managed_agents/spawn_hash.rs index 4d8054928..b67ec7ad4 100644 --- a/desktop/src-tauri/src/managed_agents/spawn_hash.rs +++ b/desktop/src-tauri/src/managed_agents/spawn_hash.rs @@ -115,6 +115,10 @@ pub(crate) fn spawn_config_hash( record.model.hash(&mut hasher); record.provider.hash(&mut hasher); record.auth_tag.hash(&mut hasher); + // Display name is written into AGENTS.md / nest identity and used for + // @mentions mid-session; a rename must trip needsRestart so running + // agents pick up the new identity (issue #1823). + record.name.hash(&mut hasher); record.respond_to.as_str().hash(&mut hasher); // The allowlist is hashed as the env receives it: spawn sets // BUZZ_ACP_RESPOND_TO_ALLOWLIST only in allowlist mode, and normalized diff --git a/desktop/src-tauri/src/managed_agents/spawn_hash/tests.rs b/desktop/src-tauri/src/managed_agents/spawn_hash/tests.rs index 6438b3b37..6ba5bee23 100644 --- a/desktop/src-tauri/src/managed_agents/spawn_hash/tests.rs +++ b/desktop/src-tauri/src/managed_agents/spawn_hash/tests.rs @@ -148,6 +148,19 @@ fn record_prompt_edit_changes_hash() { ); } +#[test] +fn record_name_edit_changes_hash() { + // Renames regenerate AGENTS.md; running agents must restart to see the + // new display name in core memory / mention routing. + let rec = record(); + let mut edited = record(); + edited.name = "Renamed Scout".into(); + assert_ne!( + spawn_config_hash(&rec, &[], &[], "wss://ws.example", &Default::default()), + spawn_config_hash(&edited, &[], &[], "wss://ws.example", &Default::default()) + ); +} + #[test] fn persona_runtime_edit_changes_hash() { // The harness command resolves live personas at spawn, so a persona From cc5f7fa44b17cc7eef9e9f6ad78bab2cc4e9a2c3 Mon Sep 17 00:00:00 2001 From: Taksh Date: Thu, 23 Jul 2026 15:20:51 +0300 Subject: [PATCH 2/3] fix(desktop): keep standalone agent avatars visible 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 Co-authored-by: Cursor --- desktop/src/features/agents/ui/UnifiedAgentsSection.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx b/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx index 5b6da92c2..a3c0033b2 100644 --- a/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx +++ b/desktop/src/features/agents/ui/UnifiedAgentsSection.tsx @@ -351,6 +351,10 @@ function StandaloneAgentCard({ }) { const title = agent.name; const profileQuery = useUserProfileQuery(agent.pubkey); + const avatarUrl = firstAvatarUrl( + agent.avatarUrl, + profileQuery.data?.avatarUrl, + ); const friendlyError = friendlyAgentLastError( agent.lastError, agent.lastErrorCode, @@ -364,7 +368,7 @@ function StandaloneAgentCard({ avatar={ onStartAgent(agent.pubkey)} /> } - avatarUrl={profileQuery.data?.avatarUrl} + avatarUrl={avatarUrl} dataTestId={`managed-agent-${agent.pubkey}`} label={title} modelLabel={ From c800f48f457b061435d3442c9e651405e4e8c82c Mon Sep 17 00:00:00 2001 From: Taksh Date: Thu, 23 Jul 2026 15:20:51 +0300 Subject: [PATCH 3/3] ci: reject in-place migration edits Fail PRs that modify shipped migrations so sqlx checksums stay valid on upgrade. Signed-off-by: Taksh Co-authored-by: Cursor --- .github/workflows/ci.yml | 5 ++++ scripts/check-migration-immutability.sh | 40 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100755 scripts/check-migration-immutability.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f1e2a989..b39281e19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,6 +61,11 @@ jobs: - '.github/workflows/ci.yml' - name: Release workflow source contract run: scripts/test-release-ref-contract.sh + - name: Migration immutability + if: github.event_name == 'pull_request' + run: | + git fetch --depth=1 origin "${{ github.base_ref }}" + scripts/check-migration-immutability.sh rust-lint: name: Rust Lint diff --git a/scripts/check-migration-immutability.sh b/scripts/check-migration-immutability.sh new file mode 100755 index 000000000..fcf74fdd2 --- /dev/null +++ b/scripts/check-migration-immutability.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Fail if a PR edits a migration that already exists on the base branch. +# +# sqlx stores a checksum per applied migration. Editing a shipped migration +# in place makes every long-lived database refuse to start on upgrade +# ("migration N was previously applied but has been modified") — see #2472. +# New migration files are fine; only content changes to pre-existing paths fail. + +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT" + +if [[ "${GITHUB_EVENT_NAME:-}" == "pull_request" ]]; then + BASE_REF="${GITHUB_BASE_REF:-main}" + git fetch --depth=1 origin "$BASE_REF" 2>/dev/null || true + BASE="origin/${BASE_REF}" +else + # Local / push: compare against the previous commit when available. + BASE="${MIGRATION_IMMUTABILITY_BASE:-HEAD^}" +fi + +if ! git rev-parse --verify "$BASE" >/dev/null 2>&1; then + echo "check-migration-immutability: base '$BASE' unavailable; skipping" + exit 0 +fi + +# Paths under migrations/ that exist on BASE and differ at HEAD. +# Two-dot diff stays reliable on shallow CI checkouts (three-dot needs a merge base). +changed="$(git diff --name-only --diff-filter=M "$BASE" HEAD -- migrations/ || true)" + +if [[ -z "${changed}" ]]; then + echo "check-migration-immutability: no pre-existing migration files modified" + exit 0 +fi + +echo "check-migration-immutability: refusing in-place edits to shipped migrations:" >&2 +echo "${changed}" | sed 's/^/ /' >&2 +echo "Add a new migration instead (append-only). See #2472." >&2 +exit 1