Skip to content

fix(desktop): resolve agent profiles through one archive-aware selector - #5706

Merged
wpfleger96 merged 2 commits into
mainfrom
duncan/archived-instance-filter
Aug 17, 2026
Merged

fix(desktop): resolve agent profiles through one archive-aware selector#5706
wpfleger96 merged 2 commits into
mainfrom
duncan/archived-instance-filter

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Aug 12, 2026

Copy link
Copy Markdown
Member

Agent profiles resolve through one shared selector (pickProfileAgent) at every entry point — the persona card, the profile panel, and library grouping. That selector ranked instances only by active/name, with no archive awareness, so a relay-archived instance early in file order could hijack the persona card and the profile panel. The persona card also recorded a durable pubkey target, which could strand the panel on an archived identity when the click landed during the archive-snapshot fail-open window. The profile panel's Runtime → Instances roster had the same blind spot: it rendered every persona instance raw, so archived instances appeared mixed in with live ones as if active.

This makes the shared resolution path archive-aware via the existing fail-open useIsArchivedPredicate:

  • pickProfileAgent filters archived instances before ranking and returns undefined when every instance is archived (persona-only mode).
  • buildUnifiedGroups drops archived agents from the standalone Custom agents and Unknown agents buckets; matched persona groups keep their full list and rely on the selector's persona-only fallback.
  • useCanonicalManagedAgentProfile resolves through a pure resolveCanonicalManagedAgent helper that applies the target-provenance rules: a deliberately requested archived pubkey stays exact (so its archive controller can unarchive it, even when a live sibling exists), preserveRequestedInstance still pins a Runtime → Instances selection, and non-archived historical navigation keeps its canonicalization.
  • The persona card's main click records a persona target that re-resolves every render, so it self-corrects to a live sibling after hydration. Deliberate instance navigation and the runtime-error affordance keep their explicit-pubkey path.
  • The Runtime → Instances roster (ProfileInstancesSection) buckets instances off the same predicate via bucketPersonaInstances: live rows render as before, and archived rows move under a labeled Archived subsection. The instance count reflects both buckets, and archived rows keep their explicit-pubkey click so unarchive stays UI-reachable (the deliberate-navigation path above).

The predicate is fail-open (treats every identity as live while the relay archive snapshot loads) and self-exempt, so a cold start never hides an identity and a user is never folded from their own client. While the snapshot is loading, every instance renders in the live list — nothing hidden, nothing labeled.

@wpfleger96
wpfleger96 requested a review from a team as a code owner August 12, 2026 21:55

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewing on Wes Pfleger's behalf.

The archived-primary path described in this PR is still reachable from the main Agents library, so this does not fully fix the reported navigation bug.

UnifiedAgentsSection chooses profileAgent = pickProfileAgent(group.agents) without archive state (desktop/src/features/agents/ui/UnifiedAgentsSection.tsx:130-159). When a persona card has any instance, AgentPersonaCard then always calls onOpenAgentProfile(agent.pubkey) (:313-321). AgentsScreen serializes that as the explicit profile target (desktop/src/features/agents/ui/AgentsScreen.tsx:69-76). That means UserProfilePanel reaches the explicit-pubkey branch in resolveProfileManagedAgent, which intentionally returns the archived record verbatim, and never exercises the new archive-aware persona fallback.

Concretely, if pickProfileAgent selects the archived Duncan (it prioritizes active status, then name), clicking Duncan's card still displays that archived Duncan as the primary profile. The Instances list is filtered afterward, but the profile identity, status/actions, channels, activity, and queries remain bound to the archived pubkey.

Please make the persona-card entry path archive-aware, for example by selecting a non-archived profileAgent before opening an explicit pubkey, or by navigating the card via the persona target and reserving explicit-pubkey navigation for clicks on a specific instance. Add a regression test that follows the caller contract (archived selected candidate plus live sibling) rather than testing only the currently bypassed persona branch.

The new resolver tests intentionally codify behavior changes (including explicit archived selection and all-archived fallback); those semantics should remain visible in the PR review.

@wesbillman

Copy link
Copy Markdown
Collaborator

Correction to the attribution in my changes-requested review: I conflated two names. Wes Billman owns the authenticated GitHub account through which this automated review was submitted; Will Pfleger is the PR author. There is no “Wes Pfleger” involved. The review was produced by Carl, an automated reviewer, and the technical finding is unchanged. Sorry for the confusion.

@wpfleger96 wpfleger96 changed the title fix(desktop): hide relay-archived agents from profile Instances fix(desktop): keep relay-archived agents off the Agents nav Aug 12, 2026

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Re-reviewed exact head 2e19767a88328ab66320b5580f3af626f0138f5d. My prior blocker is resolved.

The Agents-library caller now passes the archive predicate into pickProfileAgent, which removes archived candidates before active/name sorting. A mixed persona therefore opens the live sibling; an all-archived persona gets undefined and follows the existing persona-only navigation path. Archived standalone and unknown-persona cards are also removed, closing the adjacent explicit-pubkey entry paths. Direct explicit-pubkey profile navigation remains intentionally exact for manage/unarchive access.

The all-archived panel behavior is now consistent with the title: persona resolution returns no managed agent and the Instances section receives an empty list rather than restoring archived rows.

The added behavior-changing tests cover the actual caller selection contract, all-archived persona fallback, standalone/unknown filtering, fail-open loading, profile resolution, and Instances filtering. Focused resolver/group tests pass (25/25), desktop typecheck passes, and git diff --check is clean at this head.

I found no remaining material code issue. I am leaving this as a comment rather than approving because Wes has not explicitly authorized an approval review for this PR. Existing exact-head CI was still running in several Desktop jobs at my review snapshot.

@wpfleger96
wpfleger96 enabled auto-merge (squash) August 12, 2026 22:40

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Requesting changes after a fresh lifecycle review. Princess Donut identified a valid loading-state race that my previous re-review missed.

useIsArchivedPredicate() deliberately returns false before the archive snapshot exists. During that window, pickProfileAgent can select the archived active/name-preferred sibling. The persona card then navigates by that candidate's explicit pubkey (UnifiedAgentsSection.tsxAgentsScreen), and resolveProfileManagedAgent deliberately preserves explicit-pubkey targets after hydration. When the archive snapshot arrives, the panel recomputes but remains pinned to the archived identity. This turns a transient fail-open window into a durable wrong-primary panel until it is closed and reopened.

Please keep persona-card navigation as a persona target so archive hydration can retarget the panel. The selected live agent may still drive card presentation/actions, and deliberate instance/error navigation may remain explicit-pubkey based. Add a regression composing the actual transition: archive state unavailable → persona card chooses the old preferred record → archive state arrives with that record archived → target resolves to the live sibling (or persona-only when all are archived).

The steady-state filtering added in this head is sound, but it does not close this lifecycle path.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Princess Donut, an automated reviewer, commenting via Wes’s GitHub account after alignment with Carl and Mongo.

Request changes — the persona-target fix introduces a selected-instance mismatch whenever a persona has multiple live siblings.

UnifiedAgentsSection chooses the instance represented by the card with pickProfileAgent(group.agents, isArchived) (desktop/src/features/agents/ui/UnifiedAgentsSection.tsx:135-156). That selector filters archived records, then deliberately ranks the remaining instances by active status and name (desktop/src/features/agents/ui/unifiedAgentGroups.ts:51-63). The card’s avatar, status, actions, error state, and optional Runtime-tab target all come from that selected instance.

The main click now records only the persona (UnifiedAgentsSection.tsx:321-332). In the panel, however, resolveProfileManagedAgent resolves that persona with a raw file-order find over the first non-archived sibling (desktop/src/features/profile/ui/UserProfilePanelUtils.ts:181-184). It does not apply the card’s active/name policy.

Concrete failure: with managed-agent order [stopped Abe, running Zed], the card displays and acts as running Zed, but clicking it opens Abe. The panel then binds profile queries, status/actions, channels, activity, logs, and archive controls to Abe (desktop/src/features/profile/ui/UserProfilePanel.tsx:192-234). The stopped-error variant is more misleading: an errored alphabetical instance can make the card request the Runtime tab, while the panel resolves a different healthy file-first sibling. The previous explicit-pubkey click preserved the exact represented instance; this head loses that contract while fixing hydration pinning.

The new mounted transition test misses the divergence because its expected live target is also the first remaining live record (UnifiedAgentsSectionCardTarget.test.mjs:226-273). The resolver tests likewise do not compose multiple live siblings in conflicting file-order versus active/name order.

Smallest safe remedy: retain persona URL targeting so archive hydration can self-correct, but make persona resolution consume the same shared archive-aware active→name selector as the card. Do not duplicate the policy. Add regressions with reversed file order for (1) active preference, (2) same-status name preference, and ideally (3) the stopped-error Runtime-tab path.

The archive filtering, all-archived persona-only behavior, standalone/orphan filtering, and fail-open hydration correction are otherwise sound. Exact head reviewed: f6c0045d10d94ff1b17559eeea5f92fac646b6a6; all reported exact-head checks are green, and git diff --check is clean. CI cannot detect this because the new tests encode matching order on both sides.

@wpfleger96 wpfleger96 changed the title fix(desktop): keep relay-archived agents off the Agents nav fix(desktop): resolve agent profiles through one archive-aware selector Aug 13, 2026
@wpfleger96 wpfleger96 closed this Aug 14, 2026
auto-merge was automatically disabled August 14, 2026 17:06

Pull request was closed

@wpfleger96
wpfleger96 force-pushed the duncan/archived-instance-filter branch from dfa2f41 to 17d2147 Compare August 14, 2026 17:06
@wpfleger96 wpfleger96 reopened this Aug 14, 2026
@wpfleger96
wpfleger96 force-pushed the duncan/archived-instance-filter branch from 4fec52c to 578a957 Compare August 17, 2026 16:12
Duncan and others added 2 commits August 17, 2026 13:06
Profile resolution funnels every entry point through the shared
pickProfileAgent selector, but it ranked instances purely by
active/name — a relay-archived instance early in that order could
hijack the persona card and the profile panel, and the persona card
recorded a durable pubkey target that stranded the panel on an archived
identity when the click landed during the archive-snapshot fail-open
window.

Make pickProfileAgent and the library grouping archive-aware via the
fail-open useIsArchivedPredicate, and have the persona card record a
persona target that re-resolves each render. A deliberately requested
archived pubkey still stays exact so its archive controller can
unarchive it, and Runtime instance pinning and the runtime-error
affordance keep their explicit-pubkey path.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
The Runtime > Instances roster rendered every persona instance raw, so
relay-archived instances appeared mixed in with live ones as if active —
the original Layer-2 confusion the archive-aware selector work set out to
fix. Bucket the roster off the same fail-open useIsArchivedPredicate the
selector uses (one policy, no duplication) and render archived rows under
a labeled Archived subsection. Archived rows keep the explicit-pubkey
click so unarchive stays UI-reachable. While the archive snapshot loads
the predicate returns false, so every row renders live — nothing hidden
or labeled.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 force-pushed the duncan/archived-instance-filter branch from 578a957 to bf7e986 Compare August 17, 2026 17:18

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Requesting changes at exact head bf7e986a04ba831938f77d254ca09b2b9a9bb070 after consolidated Royal Court review.

High — ordinary navigation to an archived historical instance is incorrectly treated as deliberate instance selection.

resolveCanonicalManagedAgent returns directManagedAgent for any archived requested pubkey before the preferDirectManagedAgent branch can apply pickDirectProfileAgent (desktop/src/features/profile/lib/useCanonicalManagedAgentProfile.ts:50-63). But ordinary profile entry points carry only a pubkey. For example, message/avatar navigation calls openProfilePanel(pubkey) (desktop/src/features/profile/ui/UserProfilePopover.tsx:261-271, 347-366). Therefore an old message from an archived, stopped persona instance remains pinned to that retired identity even when a live running sibling exists. The panel then binds profile data, actions, activity, and archive controls to the wrong primary instance, contradicting pickDirectProfileAgent’s documented historical-navigation contract (desktop/src/features/agents/lib/pickProfileAgent.ts:32-51).

The Runtime → Instances path already supplies the provenance needed to preserve exactness: its row click records requestedInstancePubkey, which becomes preserveRequestedInstance (desktop/src/features/profile/ui/UserProfilePanel.tsx:182-200, 831-835). Restrict archived-instance exactness to that explicit provenance. Ordinary archived pubkey opens should continue through pickDirectProfileAgent; a historical key with no managed/persona match still falls back to the requested pubkey naturally.

Please add a regression for an archived stopped direct instance plus a live running sibling with preferDirectManagedAgent: true and preserveRequestedInstance: false. The current test at resolveCanonicalManagedAgent.test.mjs:141-157 codifies the overbroad short-circuit instead.

The archive filtering, shared ranking, persona-card hydration correction, and labeled archived Runtime subsection otherwise look coherent. Focused changed tests pass 30/30; desktop typecheck and desktop checks pass. This is a provenance defect those tests currently bless, not a CI failure.

@wesbillman
wesbillman dismissed their stale review August 17, 2026 17:42

Carl, an automated reviewer, correcting a review submitted via Wes’s GitHub account. I am retracting this blocker. The described behavior exists, but I overstated it as a defect: this PR and its tests deliberately keep direct archived-pubkey opens exact so the archive controller remains reachable for unarchive. Without a confirmed product requirement that ordinary historical-message/avatar navigation canonicalize to a live sibling, the conflicting selector documentation establishes contract ambiguity, not a release-blocking correctness bug. Exact head bf7e986 now has all reported checks terminal and successful or intentionally skipped. I found no remaining material issue.

@wpfleger96
wpfleger96 merged commit d12d825 into main Aug 17, 2026
24 checks passed
@wpfleger96
wpfleger96 deleted the duncan/archived-instance-filter branch August 17, 2026 17:46
wpfleger96 pushed a commit that referenced this pull request Aug 17, 2026
…p-repair

* origin/main:
  Rename Bumble agent to Pollen (#5864)
  fix(desktop): resolve agent profiles through one archive-aware selector (#5706)
  fix(acp): gate relay-signed workflow messages on their attributed author (#6129)
  fix(acp): replace Goose native system prompt (#5964)
  feat(workflows): add responsive library card actions (#6008)
  fix(desktop): enforce shared agent access across devices (#6086)
  feat(model-capabilities): drive model capabilities and labels from one manifest (#5597)
  docs: refresh agent development guidance (#6049)
  feat(mobile): require device authentication for identity export (#5116)
  fix(desktop): hide the offcanvas-collapsed sidebar so it stops painting over the community rail (#5947)
  Polish mobile message threads and composer (#5645)
  chore(release): release Buzz Desktop version 0.5.14 (#5917)
  ci(release): remove desktop smoke gate (#5914)
  chore(release): release Buzz Desktop version 0.5.13 (#5912)
  fix(ci): read Playwright version without nested shell quoting (#5910)
  fix(desktop): restore the agent trading-card mint button (#5900)
  Projects v3: unify sharing, discussions, and issue ownership (#5792)
  chore(release): release Buzz Desktop version 0.5.12 (#5903)
  fix(mobile): unwrap batched observer telemetry (#5805)
  perf(desktop): update active turns incrementally (#5897)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>

# Conflicts:
#	desktop/src-tauri/src/migration.rs
morgmart added a commit that referenced this pull request Aug 17, 2026
…graphy-staging

* origin/main:
  Remove GitHub security advisory commitment (#6144)
  Rename Bumble agent to Pollen (#5864)
  fix(desktop): resolve agent profiles through one archive-aware selector (#5706)
  fix(acp): gate relay-signed workflow messages on their attributed author (#6129)
  fix(acp): replace Goose native system prompt (#5964)
  feat(workflows): add responsive library card actions (#6008)
  fix(desktop): enforce shared agent access across devices (#6086)
  feat(model-capabilities): drive model capabilities and labels from one manifest (#5597)

Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
wpfleger96 pushed a commit that referenced this pull request Aug 17, 2026
…gaps

* origin/main:
  fix(desktop): align preview sidebar row styling (#6163)
  fix(desktop): repair dropped team membership links at boot and on edit (#5904)
  fix(cli): keep project replacement timestamps at or after wall clock (#5666)
  Remove GitHub security advisory commitment (#6144)
  Rename Bumble agent to Pollen (#5864)
  fix(desktop): resolve agent profiles through one archive-aware selector (#5706)
  fix(acp): gate relay-signed workflow messages on their attributed author (#6129)
  fix(acp): replace Goose native system prompt (#5964)
  feat(workflows): add responsive library card actions (#6008)
  fix(desktop): enforce shared agent access across devices (#6086)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
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.

2 participants