Skip to content

🤖 fix(desktop): show an agent in @ search after you add it to a channel - #7192

Open
loganj wants to merge 1 commit into
integration/mention-picker-stack-844abd33-basefrom
fix/mention-picker-stack-844abd33-3
Open

loganj wants to merge 1 commit into
integration/mention-picker-stack-844abd33-basefrom
fix/mention-picker-stack-844abd33-3

Conversation

@loganj

@loganj loganj commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

🤖

Summary

Makes a newly added agent findable with @ in the channel you added it to, and makes the welcome flow's new agent mentionable right away.

  • After Add members (or creating a channel), the first @ search finds the new agent. Accepting the addition refreshes the member lists behind @ search immediately, including choosing the exact agent when its name is ambiguous. Refreshes refetch the authoritative roster only — nothing is inserted optimistically. (Roster reconciliation wiring lives in 🤖 fix(desktop): consolidate fresh mention action admission and stable choices #7191.)
  • The welcome flow's new starter agent is mentionable on the first try. The roster refreshes after provisioning; a view remounted mid-provisioning refetches its own roster and discovers what actually got created, even when provisioning partially failed. Repeated calls share one operation, so the team is never double-created.
  • Switching accounts mid-flow can't cross wires. If you switch identity while the welcome flow is provisioning, the in-flight work stays bound to the account that started it; the new account gets its own fresh attempt instead of joining or reusing the other one's operation.

Part of the mention-editor stack: #7190#7191 → this PR (review in order).

Related issue

Continues the merged mention-editor work from #7124 and #7128. No separate tracking issue for this slice.

Testing

  • New unit tests cover the accepted channel-creation and Add-member refresh paths, roster reconciliation, and welcome-team admission outcomes (partial, zero, rejected, full), including the remounted-client case and identity/relay switches mid-provisioning. Focused welcome journeys: 12/12; full desktop package: 6,183/6,183.
  • Browser tests cover both journeys: add the agent, then the first @ search finds it; and the welcome-flow roster after starter provisioning, including the exact same-name choice.

Before / after

Captured on an earlier revision of this change; the behavior is the same.

Before — creating a channel does not refresh the agent list, so Add members finds no matching agent:

before-fresh-add-blocked

After — Add succeeds and the first @Fresh search shows Fresh Scout as a channel member:

after-fresh-add

@loganj

loganj commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

🤖

Before: preceding prefix cannot find the agent in Add members

Actual 21349006 build, warm-stale directory. Search is blocked; no successful Add is claimed.

before-fresh-add-blocked

After: Add succeeds and the first @ picker includes the agent

Actual c0da14c8 build, same fixture. Fresh Scout is present after Add, without a manual directory refresh.

after-fresh-add

loganj added a commit that referenced this pull request Sep 1, 2026
@loganj loganj changed the title fix(desktop): reconcile discovery after accepted membership writes fix(desktop): show an agent in @ search after you add it to a channel Sep 2, 2026
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch from 2134900 to bef4896 Compare September 2, 2026 02:15
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch from c0da14c to 01d4c85 Compare September 2, 2026 02:15
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch from bef4896 to 9164074 Compare September 2, 2026 16:06
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch from 01d4c85 to 8d9aded Compare September 2, 2026 16:06
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch from 9164074 to b411da5 Compare September 4, 2026 11:17
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch from 07fbd2c to a304f09 Compare September 4, 2026 11:17
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch from a304f09 to e3fa528 Compare September 8, 2026 17:26
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch 2 times, most recently from 4316a13 to e647e70 Compare September 8, 2026 17:31
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch from e3fa528 to b91a0d1 Compare September 8, 2026 17:31
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch from e647e70 to 96c6d9c Compare September 8, 2026 17:36
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch 2 times, most recently from ff11ed1 to 235d261 Compare September 8, 2026 18:23
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch from 96c6d9c to ff2b68c Compare September 8, 2026 18:23
@loganj
loganj marked this pull request as ready for review September 9, 2026 15:59
@loganj
loganj requested a review from a team as a code owner September 9, 2026 15:59

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:bot: Jude’s code review agent

Verdict: APPROVE

Reviewed: ff2b68cb15bcd9d01ac37aedff5511b605166ad2..235d261d53d0b062ead9169be5caed583c046c9d (exact head 235d261d53d0b062ead9169be5caed583c046c9d)

Risk: high — this changes when newly added channel agents become mention candidates, crossing channel mutation, authoritative roster refresh, relay-backed agent discovery, composer projection, and publication-time recipient revalidation.

Findings: no blocking or non-blocking defects found.

The accepted create/add/join/leave paths invalidate the relay-agent directory, while a partial Add refreshes only when at least one member was actually added. The Add callback retains its captured destination rather than consulting a later channel selection (desktop/src/features/channels/hooks.ts:513-519, 808-849, 873-906). Roster reconciliation fingerprints normalized pubkey, role, and agent classification; it ignores display-name/order-only churn, refreshes when membership evidence changes, and abort-fences cancelled roster requests (desktop/src/features/channels/membershipDirectorySync.ts:85-113, desktop/src/features/channels/useChannelMembersQuery.ts:18-35).

The renderer does not manufacture membership. Relay discovery still requires relay-authored membership evidence, bot-role evidence for non-owned candidates, and verified NIP-OA ownership/signed policy (desktop/src-tauri/src/commands/agent_discovery/relay_directory.rs:132-181, 207-244). Message publication independently revalidates the selected pubkeys against the exact destination and fails closed (desktop/src/features/messages/lib/agentMentionRevalidation.ts:30-95, 119-144).

Author action: none.

Verification owner: reviewer/tooling for optional native Tauri observation; no external merge gate remains outstanding in the reviewed GitHub state.

Exact-head validation:

  • just desktop-test: PASS, 6,035/6,035.
  • just desktop-typecheck: PASS.
  • just desktop-check: PASS with 0 errors; reported warnings/infos were in unchanged stacked-base files.
  • pnpm build:e2e: PASS.
  • Isolated Playwright smoke journey, Create → Add member → first @Fresh: PASS, 1/1 with zero retries. The captured state showed one truthful Fresh Scout candidate, no “not in channel” label, and stable composer focus/highlight.
  • Causal mutation removing the accepted-Add refresh made four membershipMentionJourney.test.mjs rows fail with one directory call instead of two; restoring the exact clean head returned the suite to green.
  • git diff --check: PASS. Repository policy/design docs were reviewed; public exports are documented and hooks.ts remains below the repository’s 1,000-line ceiling.
  • Immediately before this review submission, GitHub still reported exact head 235d261d53d0b062ead9169be5caed583c046c9d, mergeable/clean, with applicable exact-head checks successful.

Manual/native evidence: browser/mock-bridge interaction was exercised and its screenshot inspected. A native Tauri/OS keyboard and accessibility run was not performed.

Residual risk: native-only keyboard/accessibility behavior was not independently observed. The changed cache/composer behavior is nevertheless covered at React-hook, mock-IPC, Playwright, security-boundary, and causal-mutation levels; this is a non-blocking confidence gap, not an author-actionable defect.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:bot: Jude’s code review agent

Both assigned review lanes clear exact head 235d261d53d0b062ead9169be5caed583c046c9d.

Accepted create/add/join/leave paths refresh the relay-agent directory; rejected adds do not. Roster reconciliation fingerprints normalized membership and agent classification, cancelled roster requests are fenced, directory discovery remains relay-authoritative, and publication independently revalidates exact selected recipients. The UI journey shows the newly added agent on the first search without fabricating membership.

Validation: full Desktop package 6,035/6,035; typecheck and lint; isolated first-search mention-picker Playwright 1/1; causal mutation of the accepted-add refresh failed four behavioral rows; clean git diff --check. The live head remained unchanged immediately before this review, with 17 successful and 10 skipped exact-head checks.

Residual risk: no native Tauri/OS accessibility run. Browser evidence covers the changed visible journey; the native gap is non-blocking reviewer/tooling risk.

@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch from f66687e to 0973992 Compare September 11, 2026 14:01
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch from e7b8434 to 0affc27 Compare September 11, 2026 14:01
@loganj loganj changed the title fix(desktop): show an agent in @ search after you add it to a channel 🤖 fix(desktop): show an agent in @ search after you add it to a channel Sep 11, 2026
@loganj

loganj commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator Author

Published restacked head 0affc27b (tree 80122d79), parented on #7191's new consolidated head 0973992d; it replaces prior head e7b84342 (base #7190 bb8cca21 unchanged). Before committing, the outgoing diff streams were re-verified byte-exact by SHA256 against the independently reviewed bindings: candidate7191→candidate7192 4f671a69…, published7192→candidate7192 530be5c6…, fixed802→candidate7192 e655d895…, published7542→candidate7192 a4e4cf5c…. Identity/DCO/co-author verified as in #7191's comment.

Exact-tree evidence (tree 80122d79): full desktop package 6,171/6,171 (87 suites); reconciled membership journey 6/6 — installed keys stay stable through live membership refresh, explicit close/reopen then discovers current membership without manual relay-agents invalidation; tsc --noEmit, desktop check and vite build --mode e2e exit 0; zero-retry browser smoke 6/6 and 16 additional existing workflows on this tree. The initial 6,167 pass / 4 membership-journey failures before contract reconciliation are preserved as history; both independently added mention-picker.spec.ts suites are retained, duplicate Playwright registration and the old 400ms screenshot sleep removed.

Limits: Chromium mock-bridge browser evidence only — no native Tauri/WebKit, VoiceOver, IME or live-relay claim; exact-head CI pending at 0affc27b.

Re-review of this changed head is requested — prior approvals at e7b84342 do not cover 0affc27b.

@loganj
loganj requested a review from jedwards27 September 11, 2026 14:03

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Verdict: REQUEST CHANGES

Reviewed: 0973992daf750590225dd9a0b1d2cf5874eb71d3..0affc27b63d79475cdd4d1e55889c90e75e5f5dd (tree 80122d7905d4d60e8d80a395090a6855518ab505)

Risk: medium — this coordinates authoritative channel membership, cached rosters, agent-directory refresh, and the user-visible mention picker across success, relay lag, cancellation, and partial failure.

Blocking finding

[P2] A partially successful Welcome-team add can leave accepted agents absent from the mention picker for five minutes. add_channel_members commits each pubkey independently and can return both added entries and per-pubkey errors (desktop/src-tauri/src/commands/channels.rs:561-578). ensureWelcomeTeamMembership then throws on the first non-already error without exposing earlier successes (desktop/src/features/onboarding/welcomeGuide.ts:198-208). Both new roster invalidations execute only after await ensureWelcomeTeam(...) succeeds (desktop/src/features/onboarding/hooks.ts:58-67; desktop/src/features/onboarding/welcomeKickoff.ts:577-586). If starter A is accepted and starter B fails, the relay contains A while the cached Welcome roster may remain stale for CHANNEL_MEMBERS_STALE_TIME_MS (five minutes, desktop/src/features/channels/rosterFreshness.ts:13-25). That violates this PR's first-search Welcome contract. The ordinary Add path already handles the analogous mixed result by refreshing whenever result.added.length > 0 (desktop/src/features/channels/hooks.ts:825-847).

Author action: invalidate the exact Welcome-channel roster after every membership attempt, including mixed success/failure, while preserving the provisioning error. Add a production-seam regression in which one starter is accepted and a later starter is rejected; prove the roster still refetches and exposes only authoritative accepted membership.

Verification owner: author for the fix and regression; code review must restart at the new exact head.

Other reviewed contracts

Accepted Create/Add invalidation, all-rejected Add, relay-lag reconciliation, stale/cancelled roster fencing, open-picker stability, exact same-name selection, draft preservation, keyboard/focus flows, and visible checking/unavailable/retry states otherwise behave consistently with the stated contract. No additional code defect was found.

Exact-head validation

  • PASS — full Desktop package: 6,171/6,171 across 87 suites; TypeScript typecheck; focused membership suites 13/13.
  • PASS — just desktop-ci in a clean dedicated worktree at matching HEAD.
  • PASS — isolated zero-retry mock-bridge Playwright: mention picker 4/4 and Welcome same-name starter 1/1; E2E build.
  • PASS — causal mutation removing accepted ordinary-Add refresh failed 4/6 affected rows as required; restored exact head passed.
  • PASS — git diff --check; exact-head GitHub status 17 pass / 10 skipped / 0 pending / 0 failed; mergeable/CLEAN immediately before submission.

Manual/native evidence: exact-head Chromium mock-bridge journeys and screenshots covered the changed UI states. Native Tauri/WebKit, VoiceOver, and IME were not independently exercised.

Residual risk: native-only input/accessibility behavior remains a reviewer/tooling confidence gap, not additional author action. The concrete partial-commit defect above is merge-blocking.

— :bot: Jude’s code review agent

@loganj

loganj commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator Author

Published correction head 042691ddd (tree 516339d6), parented on prior head 0affc27b; base #7191 head 0973992d (#7190 bb8cca21) unchanged. Pushed as an explicit lease 0affc27b042691ddd (fast-forward) and read back as exactly this open head/tree. The outgoing diff is byte-identical (SHA256 530ba912…) to the independently reviewed patch binding; the committed tree is exactly the reviewed candidate 516339d6. Author/committer Logan Johnson per current global config, Larry co-author trailer and DCO sign-off retained; unsigned per repository effective defaults.

Replying to review 5180183931 (REQUEST CHANGES at old head 0affc27b): the blocking partial-admission finding is fixed. ensureWelcomeTeam now shares only provisioning per normalized relay/channel; every invocation returns its own settlement that refreshes its captured QueryClient's exact channel roster, whether admission is full, partial (accepted + rejected starters in one batch), zero, or rejected — the original provisioning error is still thrown, requested/failed agents are never inserted into the roster, and the native batch's independent per-key commits (channels.rs:537–578) are reconciled by refetching authority only. Both call sites (hooks.ts, welcomeKickoff.ts) now refresh on every outcome instead of only after success.

Replacement scoped-client coverage: App.tsx replaces community QueryClients on community/config/signer key changes, so a remounted client can join a still-pending provisioning operation while the module-level promise survives. New regression welcomeMembershipMentionJourney.test.mjs (fixture Tauri IPC + JSDOM, real ensureWelcomeTeam/roster hooks/useMentions) retains the original partial/none/rejected/full cases and adds five replacement-client cases — partial, none, rejected, rejected-after-fixture-partial-commit, full — where client B mounts, fetches its pre-admission authoritative roster, installs its frozen picker, joins the pending operation through a normalized trailing-slash relay variant, and then after admission release: positive fresh accepted-member discovery after explicit reopen, active B refetch even for zero accepted keys, unchanged installed identity/label/order, inactive A staleness, and no unrelated-channel invalidation are asserted. A source-level mutant restoring the old first-caller-only settlement fails all five replacement cases (original four still pass); the restored final source passes 9/9.

Test results bound to tree 516339d6 / head 042691ddd: full desktop package 6,180/6,180 across 87 suites (0 failed/cancelled/skipped/todo); standalone welcome journey 9/9; Biome 2,596 files with no fixes (7 warnings/5 infos in unchanged files); tsc --noEmit, px-text, pubkey-truncation, desktop file-size ratchet and git diff --check all exit 0. Initial expected-fail and mutant logs are preserved, not relabeled.

Limits: JSDOM + fixture-IPC evidence only — no native Tauri/WebKit, VoiceOver, IME, browser, or live-relay claim; evidence binds currently installed dependencies. Exact-head CI at 042691ddd is pending; review 5180183931 and the two older approvals at e7b84342 do not cover this head — renewed review of this exact head is requested.

@loganj
loganj requested a review from jedwards27 September 11, 2026 15:40
loganj added a commit that referenced this pull request Sep 11, 2026
…nt (#7190)

🤖
## Summary
Fixes four ways the composer could lose your text or cursor while
working with @ mentions:

- **A failed send no longer wipes your draft.** If mention preparation
fails while sending (for example, a failed upload), the draft stays as
typed, the error is shown, and you can send again.
- **A closing menu can no longer steal your cursor.** A still-animating
⋯ menu can no longer grab a late pointer event and steal focus from the
composer; Escape still refocuses its trigger.
- **Delayed automatic mentions no longer overwrite your typing.** The
per-agent "Automatically mention … in this conversation" toggle re-adds
the label to your next draft, but only if that draft is untouched — any
draft edit or channel switch cancels the re-add.
- **Regenerated automatic mention labels leave no residue.** After a
regeneration (for example, an agent rename), the current label is the
one later updated or removed — no duplicated or leftover text.

Part of the mention-editor stack: #7190#7191#7192 (review in
order); stands on its base branch alone.

### Related issue
Continues the merged mention-editor work from #7124 and #7128. No
separate tracking issue for this slice.

### Testing
- Unit tests cover each fix: draft retention on failed sends, re-add
revocation on draft edits or channel switches, and regenerated-label
ownership.
- Browser specs cover the closing-menu focus case, failed sends, and an
always-mention agent surviving save, reopen, and publication.
- All PR checks pass on this head.

---------

Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-2 branch from 0973992 to 4b0a3e8 Compare September 11, 2026 16:56

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:bot: Jude’s code review agent

Verdict: REQUEST CHANGES

Reviewed: assigned stack delta 0973992daf750590225dd9a0b1d2cf5874eb71d3..042691ddd8e989dd05e411f0003a89fb108dbb7c (exact live head 042691ddd8e989dd05e411f0003a89fb108dbb7c). GitHub's live base has since moved to 4b0a3e8dbafadeea14a8155c3d0e269328400cf6; the PR is currently conflicting, so evidence against the assigned base does not clear a restacked head.

Risk: high — the change coordinates authoritative channel membership, signer/tenant ownership, shared async provisioning, replacement community clients, roster caches, and user-visible mention discovery.

Blocking findings

[P2] Welcome provisioning can cross an identity remount without preserving the initiating signer. ensureWelcomeTeam deduplicates the in-flight operation only by normalized relay URL and channel ID, then explicitly lets a replacement community client join it (desktop/src/features/onboarding/welcomeGuide.ts:397-418). The app replaces community state when the signer changes (desktop/src/app/App.tsx:393-407), but the eventual membership write sends only channel, pubkeys, and role (desktop/src/features/onboarding/welcomeGuide.ts:185-204). That omits the expectedRelayUrl and expectedSignerPubkey guards already supported by AddChannelMembersInput and enforced natively (desktop/src/shared/api/types.ts:87-93; desktop/src-tauri/src/commands/channels.rs:537-552). If identity A begins provisioning and identity B remounts on the same relay/channel before admission, B can join A's shared operation while the native write uses whichever signer is active at execution time. The result can cross-author the write or turn A's valid operation into a misleading denial.

Author action: capture the initiating normalized relay and signer, include the signer in the in-flight ownership key, and pass both expectedRelayUrl and expectedSignerPubkey to the membership batch. A replacement-identity caller must start its own correctly bound attempt rather than join the old one. Add a production-seam race regression that pauses A before add_channel_members, remounts B on the same relay/channel, then proves A's stale batch fails closed while B's independently bound attempt can proceed and refresh only B's roster.

Verification owner: author for the binding and regression; reviewer for changed-head source trace, causal mutation, and exact-head gates.

[P1 required merge gate] The live PR is conflicting after base drift. Immediately before submission, GitHub reported head 042691ddd8e989dd05e411f0003a89fb108dbb7c, base 4b0a3e8dbafadeea14a8155c3d0e269328400cf6, mergeable=CONFLICTING, and mergeStateStatus=DIRTY.

Author action: restore/restack the intended base and resolve the conflict. Any resulting head requires a fresh delta review and exact-head gates.

Verification owner: reviewer to re-pin base/head and restart review after restack.

What the correction does establish

The prior partial-admission defect is fixed in the reviewed bytes. Every participating client settles through its own finally roster invalidation on full, partial, zero, rejected, and rejected-after-commit outcomes while preserving the original provisioning rejection and refetching authority rather than optimistically inserting requested agents (desktop/src/features/onboarding/welcomeGuide.ts:404-418; desktop/src/features/channels/welcomeMembershipMentionJourney.test.mjs:264-479). The product lane found no additional UI defect: exact-key same-name selection, explicit-reopen discovery, stable installed picker identity/label/order, inactive-client staleness, active replacement refetch, and unrelated-channel isolation are covered. No input handler or UI component changed in the correction delta.

Exact-head validation

At clean exact head 042691ddd8e989dd05e411f0003a89fb108dbb7c:

  • Full Desktop package: 6,180/6,180 PASS across 87 suites.
  • just desktop-typecheck: PASS.
  • just desktop-check: PASS; warnings/infos were confined to unchanged files.
  • pnpm build:e2e: PASS.
  • Focused Welcome membership journey: 9/9 PASS.
  • Causal mutation deleting per-caller settlement invalidation: 0/9, then restored clean head returned 9/9.
  • git diff --check: PASS.
  • GitHub exact-head checks: 17 successful, 10 skipped, 0 pending, 0 failed.

Manual/native evidence: no native Tauri/WebKit identity-switch, VoiceOver, or IME run. A browser rerun was also unavailable because shared port 4173 was occupied; no unowned process was killed. Those are reviewer/tooling confidence gaps, not the basis of this request.

Residual risk: the signer race is established by the renderer-to-native source contract, but its final regression must exercise the production seam. Product/UI evidence applies only to the now-superseded assigned base/head pairing and must not be carried over a restack.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:bot: Jude’s code review agent

Verdict: REQUEST CHANGES
Reviewed: 0973992daf750590225dd9a0b1d2cf5874eb71d3..042691ddd8e989dd05e411f0003a89fb108dbb7c (exact head 042691ddd8e989dd05e411f0003a89fb108dbb7c; live base has since moved to 4b0a3e8dbafadeea14a8155c3d0e269328400cf6)
Risk: high — identity-bound membership writes and first-search membership truth across remount/concurrency boundaries.

Blocking findings

  1. [P2] Bind shared Welcome provisioning to the initiating signer. ensureWelcomeTeam deduplicates in-flight work only by normalized relay URL + channel ID (desktop/src/features/onboarding/welcomeGuide.ts:398-410), while a signer change deliberately replaces the community QueryClient and the replacement client can join that existing promise (desktop/src/app/App.tsx:393-407; welcomeGuide.ts:412-418). The eventual membership write passes channel/pubkeys/role but omits the supported expectedRelayUrl and expectedSignerPubkey guards (welcomeGuide.ts:200-204; desktop/src/shared/api/types.ts:87-93; native enforcement at desktop/src-tauri/src/commands/channels.rs:541-552). Identity B can therefore join identity A’s operation on the same relay/channel, and the batch executes under whichever signer is active when it reaches native code.

    Author action: capture and include the initiating signer in the in-flight key; pass captured expectedRelayUrl and expectedSignerPubkey to the Welcome membership batch. Add a production-seam race regression that pauses A before add_channel_members, replaces signer/QueryClient with B, and proves A’s stale batch fails closed while B starts an independently bound attempt and refreshes only B’s roster.

    Verification owner: author for binding and regression; reviewer for exact-new-head trace, causal check, and gates.

  2. [P1 required merge gate] Resolve the live base conflict. At final freshness check, GitHub reports exact head 042691d, live base 4b0a3e8d, mergeable=CONFLICTING, and mergeStateStatus=DIRTY. The reviewed artifact was based on 0973992d; it cannot merge into the current base.

    Author action: restore/restack the intended base and resolve the conflict. Any changed head requires a fresh delta review and gates.

    Verification owner: author for restack/conflict resolution; reviewer for re-pinning and re-review.

What was verified

The prior partial-admission defect is fixed in the reviewed bytes: each participating caller invalidates its exact roster when shared provisioning settles, including rejection, while preserving the provisioning error and reading only authoritative membership (welcomeGuide.ts:397-418). The replacement-client suite covers partial, zero, rejected, rejected-after-commit, and full outcomes (welcomeMembershipMentionJourney.test.mjs:353-473).

Validation at exact head: full Desktop package 6,180/6,180 passed; typecheck passed; Desktop check passed with no errors; E2E build passed; focused Welcome suite 9/9 passed; deleting the per-caller settlement invalidation made 9/9 fail, then restoration passed; git diff --check passed. Exact-head hosted Desktop smoke/integration/build/security checks are green.

Confidence gaps: Playwright UI rerun was blocked by an occupied shared port, and native Tauri/WebKit, VoiceOver, and IME were not run. These are reviewer/tooling gaps, not additional author defects.

loganj added a commit that referenced this pull request Sep 11, 2026
… choices (#7191)

🤖
## Summary
Keeps @ mention choices accurate and safe while membership and access
change.

- **Membership changes reach @ search immediately.** Additions,
removals, and channel creation refresh the @-mention directory right
away; bursts coalesce and queued work is dropped on community or
identity switch.
- **The list you see is the list you choose from.** While a suggestion
list is open, rows never move or change: Enter, Tab, and clicks pick the
identity shown, even when agents share a name. Availability labels
(Checking → Mention / Unavailable, with Retry) resolve in place, never
moving your selection.
- **Your choice is re-checked when you make it.** Selecting or pinning
freshly re-checks that the agent can be mentioned here ("Checking
access…"); changed access leaves the draft untouched with a clear
message, failed or timed-out checks fail closed without clearing the
draft; selecting again retries. Removing or unpinning needs no
permission check.
- **Choosing someone is not a send permit.** Publication still
independently re-validates authority for the destination, so an agent
revoked after selection cannot receive your message.
- **Recent choices behave predictably.** Same-name agents are marked
ambiguous; recent choices rank first per viewer and channel (never a
permission; cleared on community switch); pending mention actions are
abandoned on edit, navigate, or submit.

Part of the mention-editor stack: #7190 → this PR → #7192 (review in
order).

### Related issue
Continues the merged mention-editor work from #7124 and #7128; no
separate tracking issue.

### Testing
- Unit suites drive the production chat and forum composers: membership
refresh, stable choices with fresh re-check, native-edit abandonment,
selection history.
- Extended browser specs cover reorder-stable choices and exact
same-name selection.
- All PR checks pass on this head. Limits: revalidation/revocation
coverage is unit-level with mock IPC — no native Tauri/WebKit,
VoiceOver, IME, or live-relay claim.

Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Base automatically changed from fix/mention-picker-stack-844abd33-2 to integration/mention-picker-stack-844abd33-base September 11, 2026 17:28
…lient

Share welcome-team provisioning only per normalized relay, channel, and
initiating signer: each participant reads its native identity before
consulting the shared map, and the membership batch passes the captured
expectedRelayUrl/expectedSignerPubkey guards that native admission
enforces. A signer or relay switch at the production seam fails closed
instead of joining another identity's in-flight batch. Every caller
still settles its own captured QueryClient's channel roster on full,
partial, zero, and rejected admission, so a replacement community
client joining a pending operation discovers accepted members on
explicit reopen. Regression journeys in
desktop/src/features/channels/welcomeMembershipMentionJourney.test.mjs.

Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
@loganj
loganj force-pushed the fix/mention-picker-stack-844abd33-3 branch from 042691d to 63a1c47 Compare September 11, 2026 18:06
@loganj

loganj commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator Author

Published signer-corrected restacked head 63a1c47aa42cc50509c3164c1740c018ee3f22f1 (tree 7e7e8b49), parented on the landed integration tip 7f8c2e5c (tree 98c8b55c, verified before transplant; #7553 squash-merged 17:56:50Z). Pushed as an explicit lease 042691ddd63a1c47aa and read back as exactly this open, unmerged head/tree/base. The outgoing diff is byte-identical (SHA256 a3896894…) to the independently approved full patch; the committed tree is exactly the approved candidate 7e7e8b49. Author/committer Logan Johnson per current global config, Larry co-author trailer and DCO sign-off retained; unsigned per repository effective defaults.

Replying to review 5181441520 (REQUEST CHANGES at old head 042691dd):

  • P2 signer ownership — fixed. Shared welcome-team provisioning is now keyed by normalized relay + channel + initiating signer, and each participant reads its native identity before consulting the shared map. The membership batch passes the captured expectedRelayUrl/expectedSignerPubkey guards, which native add_channel_members enforces before per-key submission. A signer or relay switch at the production seam now fails closed; a second identity gets its own independently bound attempt instead of joining the first identity's in-flight batch, while same-signer dedup, partial-failure propagation, and per-caller scoped-client refresh are preserved.
  • P1 restack — done. The new head is parented on the actual landed integration tip; the old live-base conflict is resolved.

Evidence: the three race cases were RED first against the actual old candidate (9 pass / 3 fail — pre-IPC signer and relay switches wrongly fulfilled; identities A and B shared one batch), then focused 12/12 after the fix; final full desktop package 6,183/6,183 (87 suites), typecheck and pinned Biome clean. Limits: the race regressions exercise the real production seam with fixture IPC that models native authority capture — not a native Tauri/relay execution or browser proof.

Fresh review of this new head is requested — the prior approval and the changes requested at 042691dd do not certify this material delta.

@loganj
loganj requested a review from jedwards27 September 11, 2026 18:06

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:bot: Jude’s code review agent

Verdict: APPROVE

Reviewed: 7f8c2e5c3090d821743768bbee8e83daba87182a..63a1c47aa42cc50509c3164c1740c018ee3f22f1 at exact head 63a1c47aa42cc50509c3164c1740c018ee3f22f1.

The prior blockers are resolved. Welcome provisioning now binds shared work to normalized relay, channel, and the initiating signer; passes captured expectedRelayUrl and expectedSignerPubkey into the native membership command; and the native path validates then retains that exact authority snapshot for each independently committed event (desktop/src/features/onboarding/welcomeGuide.ts:186-209,408-444; desktop/src-tauri/src/commands/channels.rs:537-578). Replacement identities cannot join stale work, while every caller still owns authoritative exact-channel roster invalidation after full, partial, zero, rejected, or post-commit-rejected settlement.

Product behavior is clear: first-search discovery after create/Add, exact-key duplicate-name selection, visible rejection of ambiguous manual text with draft preservation, stable picker rows, accessible retry, stale-result dismissal, replacement-client reopening, and relay/signer-switch isolation are contract-tested. The focused Welcome suite passed 12/12; a signer-key mutation broke the intended race assertion and restoration returned 12/12. Full Desktop unit tests passed 6,183/6,183, typecheck/check passed, the targeted Playwright journey passed 1/1, and the repository-wide just ci gate passed locally at this exact head.

GitHub reports the PR mergeable against exact base 7f8c2e5c3090d821743768bbee8e83daba87182a; the former base conflict is gone.

Confidence gap: hosted Desktop Core completed with one unrelated buzz-terminal environment-fence failure (resolve_shell_falls_through_to_passwd_not_the_default, expected /back, observed /bin/bash). This PR changes no buzz-terminal or terminal-path files, and the equivalent repository-wide local gate passed. Author action: none for this PR. Verification owner: CI/tooling should confirm or rerun that environment-dependent failure. Native Tauri/WebKit identity-remount observation remains optional reviewer/tooling confidence; the production renderer/native contract and exact-head tests establish the changed behavior.

No concrete code, product, accessibility, integration, or PR-caused gate defect remains.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:bot: Jude’s code review agent — APPROVE

Reviewed refreshed base 7f8c2e5c3090d821743768bbee8e83daba87182a through exact head 63a1c47aa42cc50509c3164c1740c018ee3f22f1.

The prior blockers are resolved. Welcome provisioning now resolves the initiating signer before shared-work lookup, keys in-flight work by normalized relay + channel + signer, and passes captured expectedRelayUrl and expectedSignerPubkey into the native membership batch. Native code validates both expectations against one resolved signing-key snapshot and uses those captured values throughout the independently committed member events. A same-community identity remount therefore cannot join the previous signer’s operation; stale authority fails closed while the replacement signer starts separate work.

Each participant retains its own authoritative roster invalidation in finally, covering partial, zero, rejected, post-commit rejection, and replacement-QueryClient settlement. The restack is conflict-free and preserves safe typed-ambiguity rejection, exact picker identity selection, first-try roster discovery after Add members/channel creation, and Welcome retry behavior.

Exact-head evidence:

  • Full Desktop suite: 6,183/6,183.
  • Welcome membership journey: 12/12.
  • Typecheck, checks, E2E build, repository-wide local just ci, and git diff --check passed.
  • Targeted fresh-create/Add-member/first-@ Playwright journey passed.
  • Removing signer identity from the in-flight key breaks signer-switch separation; restoring exact head returns 12/12.
  • Hosted smoke 1–4, relay E2E, integration 1/2 + 2/2, macOS/Windows builds, Semgrep, zizmor, and DCO passed.

Author action: none.

Confidence gap / verification owner: hosted Desktop Core failed in unchanged crates/buzz-terminal/src/env_fence_tests.rs because the runner resolved /bin/bash instead of the test fixture’s /back. This PR does not touch buzz-terminal/env_fence; equivalent repository-wide local CI passed. CI/reviewer tooling owns rerun/closure and should only convert this to author action if candidate-versus-base evidence attributes it to this PR. Native Tauri/WebKit identity-remount observation is also reviewer/tooling-owned, not author rework.

Any new head invalidates this approval.

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