Skip to content

feat(bestie): stop a former Bestie's check-ins and keep a Former Bestie tab - #2039

Open
rileycrane wants to merge 1 commit into
rileycrane/bestie-l3-check-insfrom
rileycrane/bestie-l5-former-bestie
Open

rileycrane wants to merge 1 commit into
rileycrane/bestie-l3-check-insfrom
rileycrane/bestie-l5-former-bestie

Conversation

@rileycrane

@rileycrane rileycrane commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

When you change your Bestie, the old one stops checking in, and its other settings stay where you can reach them in a Former Bestie tab.

Why: only one agent should check in on you. A former Bestie's other settings (memory, channels) are still on, so they stay reachable in their own tab instead of becoming invisible.

What changes

  • Only your Bestie checks in. Whenever the saved Bestie is known, on this device or synced from another, every other local agent has its check-in section and timer removed. Its memory section and channels stay.
  • Former Bestie tab: it shows " is no longer your Bestie. These are still on.", the same switches, Remove from all for its private channels, and Make my Bestie again. The tab shows while the agent has a Bestie section or, if this device saw it as Bestie, while it is in one of your private channels.
  • New Bestie starts remembering. An agent this device makes Bestie starts with Remembers you on (the plugin hears onBestieMade). A choice synced from another device changes nothing, so memory turned off stays off.
  • Tests: a browser layout check (tests/browser) covers the Bestie and Former Bestie tabs at two panel widths and two text sizes.

Design decisions

  • Cleanup acts only on a Bestie the account has saved. While the account is still being read, nothing is removed.
  • Former Bestie is a second tab (buzz.bestie/former-bestie), not a mode of the Bestie tab, so each tab's when stays simple.

Try it (just dev, with two local agents, Ada as Bestie with Remembers you and Every hour on)

  1. In Ada's Bestie tab, Change to Bea and confirm.
  2. Ada now has a Former Bestie tab: Remembers you is still on, Every hour is off, and its timer is gone from Watching.
  3. Bea has the Bestie tab, with Remembers you on.
  4. In Ada's Former Bestie tab, click Make my Bestie again and confirm. Ada has the Bestie tab again.

Stack: each PR is based on the one before it: #2034 Bestie tab → #2035 Remembers you → #2036 private channels → #2037 check-ins → #2039 Former Bestie (this PR) → #2041 Remove as Bestie → #2047 Choose your bestie. #2040 (recent notes in Claude Code prompts) is separate and based on main.

Overlap: #1716 also changes features/agents/service.ts and tabs.tsx. Whichever lands second will rebase onto the other.

🤖 Generated with Claude Code

buzz-review-completed

…ie tab

When the saved Bestie is known, any other agent here has its check-ins
removed, wherever the change was made; memory and channels stay. A former
Bestie with a setting still on gets a Former Bestie tab with the same
switches, Remove from all for its channels, and Make my Bestie again. An
agent made Bestie on this device starts with Remembers you on. The memory
rules date notes by this device's calendar.

The reconcile acts only on a Bestie saved to the account, as a
device-only choice may be an automatic pick. It leaves the shared
instructions of an agent that is also in another community, removing only
its timer here; tries each state once per connection; re-runs for changes
made while saving; starts each save from the agent as the last one left
it; and stops if it is made Bestie again meanwhile.

Switches, saves and the reconcile treat a section edited by hand as
present, so none adds a second one. A browser check renders the Bestie,
edited and Former Bestie tabs at 28rem and 20rem, with default and large
text, in Chromium and WebKit.

Co-authored-by: eggboy <3986e5374b8c11a274f4a53fa9a68e1e18b53e712f8aa5218add2485bf5a2b09@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Riley Crane <rileycrane@squareup.com>

@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.

🤖 Star Lord’s automated source review via Wes’s account, integrating independent Rocket, Mantis and Groot lanes.

Reviewed head 2372470cd869c8d96cf266bd3dfe68765ecfb513 against base/merge-base 0ae322732ddc6cb87733dbd22e2ea9d2b204fbec. Two actionable findings are inline (P2 lifecycle, P3 completion focus). This is non-blocking COMMENT feedback, not approval.

Read the 18-file patch, affected save/account-choice/agent/tab callers, relevant architecture/design guidance, and the public PR description and commit message; the description has no attached images. Shared SettingsGroup, PreferenceRow, Switch, Button, Menu and AlertDialog owners are reused. The three added browser cases have a browser-specific layout/overflow purpose; they do not exercise the real host’s completion focus or plugin-disposal writes.

Validation limits: source analysis only; no PR code, tests, builds or app were run. The one-time hosted-check snapshot shows latest run 41144263801 with CI required successful (36 successful jobs, Windows skipped); an earlier run has cancellations and a failed aggregate. Native behavior, live sync/teardown timing, keyboard/screen-reader behavior, both-theme visual acceptance and incremental test cost were not independently measured.

.finally(() => {
saving.delete(agent.key);
// What changed while it saved.
reconcile();

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.

🤖 [P2] Stop pending cleanup from starting writes after disposal

The disposer below only unsubscribes, so an already-started cleanup still reaches this unconditional reconcile(). For example, let a former agent’s timer save remain pending, disable the Bestie plugin, then select a different community whose saved Bestie is already known. When that save settles, this disposed worker reads the current relay/agent snapshots and can start deleting timers and instructions in that community while Bestie is disabled. Even without the community change, saveFeature starts its instruction write after awaiting the timer save (save.ts:102–114), without checking the plugin’s lifetime. This escapes the disposal barrier documented in docs/plugin-architecture.md.

Fence reconciliation and queued continuations with a disposed/lifetime check, including the boundary before the second write, and skip this final pass after disposal. A deferred-save test should dispose the plugin before resolving the timer write and assert that no further save starts.

!!snapshot.session.mainAgent &&
agent.pubkey !== current &&
inCommunity(agent, snapshot) &&
formerWithSettings(agent, snapshot)

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.

🤖 [P3] Hand focus to a surviving control when the former tab disappears

Turning off the last remaining setting (with no private-channel membership) or removing the final channel makes this predicate false while the user is operating inside the selected Former Bestie tab. AgentTabs.tsx:77–78 then selects its first section (Identity) and unmounts the active panel/control, but does not transfer focus. Its Tabs instance owns only the tab strip, and the outer AgentDetails focus effect runs only on mount, so neither supplies this completion handoff. Making the agent Bestie again similarly removes this tab without deliberately selecting the replacement Bestie tab.

Keep the intended conditional tab visibility, but explicitly hand selection/focus to a surviving tab or completion target when the selected section disappears, without stealing focus if the user already moved elsewhere. This follows the design guide’s detail-panel/focus-restoration contract. Add a host-level keyboard completion test; the standalone layout fixture cannot cover this transition.

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