Conversation
Surface the kind-0 about field as a one-line role/description under agent rows in the mention autocomplete (block#2699). Carried through the Tauri profile summary path, resolved via the existing users-batch delta cache for agents missing from the caller's profile lookup, and rendered as a truncated single line that degrades to today's plain "agent" label when about is empty. Ports upstream/block#2706 onto the fork. Fork deviations from the upstream diff, all mechanical conflict resolution, no behavior change: - useMentions.ts hunks land in buildMentionCandidates.ts, where the fork already extracted candidate building out of useMentions.ts. - The nostr_convert about-carrying test lands in nostr_convert/tests.rs, where the fork already moved `mod tests` into its own file. - Every ported mapMentionCandidateToSuggestion call gains agentProvenanceReady: true, a fork-only required opt predating this port; the six ported assertions are otherwise unchanged. - MentionAutocomplete.tsx keeps the fork's literal "agent" fallback (upstream carries an agentLabel var) and keeps showAgentProvenanceMarker inside the agent span -- both fork baseline shape, not upstream's. - mentionSuggestionMapping.test.mjs is appended to, not created; the file already exists on zs/main. Signed-off-by: webdevtodayjason <jason@webdevtoday.com> Signed-off-by: wiggdevin <202901685+wiggdevin@users.noreply.github.com>
Gemini tester (harsh mode) flagged that UserProfilePopover renders profile?.about?.trim() but no test asserted it. Add a smoke spec that seeds an agent profile with an about bio, hovers its message, and asserts the popover's user-profile-description testid shows the text. Signed-off-by: wiggdevin <202901685+wiggdevin@users.noreply.github.com>
Sol audit on port/2706 found the new agent-profile fallback in useMentions.ts batched every mentionable agent with an unknown `about` into one unlimited get_users_batch call. On a composer with no scoped `profiles` prop (New Message, Forum, project agent chat), the author set is the whole mentionable-agent directory; the relay clamps a limit-less filter to 100 rows, and a truncated page gets cached as confirmed-missing for 10 minutes across the whole app. - Extract the fallback's windowing and filtering into mentionFallbackWindow.ts (rankVisibleMentionCandidates, selectAgentProfileFallbackPubkeys): the batch is now drawn only from the ranked, visible MENTION_SUGGESTION_LIMIT (50) window, never the full candidate set, so every request stays under the relay's clamp. Re-ranking on each keystroke still brings an agent past the window into view with its own bounded request. - Fix the accessible-description gap the audit flagged in MentionAutocomplete.tsx: the row's aria-label overrode the role line as unannounced descendant text; wire it via aria-describedby instead. - Add mentionFallbackWindow.test.mjs (unit, >100 fake agents) and a New Message e2e regression (no `profiles` prop reaches the composer, so the fallback is the only thing that can resolve an about) — verified both fail when the fallback wiring is reverted. Co-authored-by: Sol audit (GPT-5.6, xhigh) Signed-off-by: wiggdevin <202901685+wiggdevin@users.noreply.github.com>
…icker Cap the untrusted kind-0 `about` fed into the mention picker's role line to 120 graphemes before it reaches the DOM (text node, title, and the accessible description). Wire the verified "managed by <owner>" provenance into aria-describedby alongside the agent's own bio, instead of only the untrusted half. Cover profileLookupsEqual's about branch at both the comparator and the useMessageProfiles hook that consumes it. Correct mentionFallbackWindow.ts's docblock, which cited the wrong relay clamp (100 instead of the actual DEFAULT_MAX_PAGE_LIMIT, 1000). Rework the e2e request-bound regression test so it actually binds the production seam: record every get_users_batch call from the first render (a new startWithUsersBatchHeld mock config knob) so an unrelated app-shell batch call can't pre-warm the per-pubkey cache and mask whether the mention fallback's own request would have been bounded, and withhold the past-window agent's about from search results (usersBatchOnlyPubkeys) so its role line can only resolve through the fallback under test. Signed-off-by: wiggdevin <202901685+wiggdevin@users.noreply.github.com>
…gaps Sol audit round 2 on port/2706 left three verified WARNs open: - The batch/search DTOs (UserProfileSummaryInfo, UserSearchResultInfo) carried an untrusted kind-0 `about` with no cap before the frontend's 120-grapheme render cap. Cap it at the boundary in nostr_convert::truncate_mention_about (512 bytes, char-boundary safe), applied in users_batch_from_events and user_search_result_from_event. - selectAgentProfileFallbackPubkeys treated any profiles[pubkey] entry as proof `about` was known, so the synthetic entries mergeAgentNamesIntoProfiles/mergeMemberAgentFlagsIntoProfiles attach to every managed/relay/member agent (name fields, no `about` key) permanently suppressed the fallback for exactly the agents it exists to cover. Key off `about === undefined` instead, normalized like the mapper does. - The name-collision branch in MentionAutocomplete nulls `ownerLabel` and falls back to the npub as the only trusted disambiguator, but the npub span had no id and was never wired into aria-describedby, so two same-name agents announced identically to screen readers. Give it an id and include it in describedBy. Tests: 2 new Rust seam tests (byte cap + char-boundary safety) plus a DTO-level truncation test on each converter, 2 new fallback-window unit tests (synthetic-entry inclusion, normalized-key match), 2 new/extended MentionAutocomplete a11y tests (npub wired into describedBy; disambiguator still present when ownerLabel is nulled). Signed-off-by: wiggdevin <202901685+wiggdevin@users.noreply.github.com>
Signed-off-by: wiggdevin <202901685+wiggdevin@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports upstream
block/buzzPR block#2706 (webdevtodayjason:feat/mention-selector-agent-about) onto the fork: the@-mention picker now shows each agent's kind-0aboutas a one-line role/description under its row, carried through the Tauri profile summary path, resolved via the existing users-batch delta cache for agents missing from the caller's profile lookup, and rendered as a truncated single line that degrades to today's plain "agent" label whenaboutis empty.Fork deviations
From
build.md(all mechanical conflict resolution — no behavior change from upstream's diff):useMentions.tshunks land inbuildMentionCandidates.ts, where the fork already extracted candidate-building out ofuseMentions.ts.nostr_convertabout-carrying test lands innostr_convert/tests.rs, where the fork already movedmod testsinto its own file.mapMentionCandidateToSuggestioncall gainsagentProvenanceReady: true, a fork-only required opt predating this port; the six ported assertions are otherwise unchanged.MentionAutocomplete.tsxkeeps the fork's literal"agent"fallback (upstream carries anagentLabelvar) and keepsshowAgentProvenanceMarkerinside the agent span — both fork baseline shape, not upstream's.mentionSuggestionMapping.test.mjsis appended to, not created; the file already exists onzs/main.Beyond the mechanical port, three rounds of adversarial review (Gemini tester, critic, and three rounds of GPT-5.6 Sol audit) drove additional hardening not present in the upstream PR:
MENTION_DESCRIPTION_MAX_GRAPHEMES,Intl.Segmenter-based, matching the existingtruncateInlineChipLabelpattern) — upstream renders the fullaboutunbounded.nostr_convert::MENTION_ABOUT_MAX_BYTES, UTF-8-char-boundary-safe truncation) applied in bothusers_batch_from_eventsanduser_search_result_from_event, bounding the untrusted kind-0aboutbefore it crosses the Tauri IPC boundary — upstream carries it across unbounded (up to ~256 MiB per batch in the worst case).useMentions.ts'sagentProfilePubkeys) now requests only the ranked, visible suggestion window (mentionFallbackWindow.ts, capped atMENTION_SUGGESTION_LIMIT= 50) instead of the entire mentionable-agent directory — upstream filters over the full candidate set with no cap.startWithUsersBatchHeld(pinsget_users_batchopen from install so every caller's request payload is captured before anything resolves and pre-warms the shared per-pubkey cache) andusersBatchOnlyPubkeys(withholds specific pubkeys fromsearch_usersresults while still resolving them viaget_users_batch, so a role line can only reach the row through the fallback under test, not through global search).aria-describedby(previously neither reached assistive technology, since the row'saria-labeloverrides all descendant text), and the name-collision npub disambiguator is included too, so two same-named agents are no longer announced identically off self-authored, untrusted text.Gates
Latest round (worktree
/Users/zero-suminc./projects/buzz-wt/port-2706, Hermit activated), rerun fresh for this PR after mergingorigin/zs/main(overlap:desktop/playwright.config.ts, clean auto-merge, no conflicts):Tested base OID (
git rev-parse origin/zs/main):625151fd4b2612d8829f3ad2b0c619e06a2ac5a0just fmt-check clippy desktop-check desktop-tauri-clippy file-size-checknode --import ./test-loader.mjs --experimental-strip-types --test src/features/messages/lib/mentionSuggestionMapping.test.mjs src/features/messages/ui/MentionAutocomplete.test.mjs src/features/messages/lib/mentionFallbackWindow.test.mjsgit rev-list origin/zs/main..HEAD×Signed-off-bypresence, verified with the realgitbinary)Earlier build/fix rounds additionally ran and passed the full
just desktop-test(6258 passed),just desktop-tauri-test, targetedcargo test nostr_convert(77 passed, including the 4 new DTO-cap tests), and isolated/targeted Playwright smoke runs for every spec touching mention descriptions, accessible-description,get_users_batch, orsearch_users. Full-suitejust desktop-e2e-smokeruns on the shared build machine repeatedly hit unrelated load/port-contention flakiness (documented at length inbuild.md); every flake was individually re-verified as non-reproducible in isolation and untouching this diff's files. Per the ticket instructions,just ci(the fork's full CI gate) was not run locally — that runs in CI on this PR.Gemini 3.8 Flash tester
Verdict: PASS. Ran all fast gates and ticket eval commands, plus an explicit adversarial/edge-case stress pass (wrong input, empty/whitespace
about, missing profile, hostile content, concurrent arrival, non-UTF-8, oversized input, keyboard-only path) — no break found.One missing-test finding: the ticket's "hover card still shows
about" acceptance clause had no test bindingUserProfilePopover.tsx's existingaboutrendering. Fixed: addedmentions.spec.ts::"agent profile popover shows the about bio".Critic
Verdict: parity (
nothing_above_nit: true). Confirmed 14/14 upstream files present, the mapping function's body character-identical to upstream's, the ported e2e spec differing from upstream's only by biome reformatting, all six ported unit tests and both ported Rust tests present and green, and all five fork deviations above named in the commit body and each independently confirmed against the diff. One initial gap — the deviations were correct but not written down anywhere landing-visible — was fixed by amending the commit message and drafting this PR body. Remaining findings are inherited-from-upstream NITs/LOW (anundefined-vs-nullcollapse for search-sourced agents with noabout, a raw-vs-normalized pubkey lookup mismatch, a dead test alias) explicitly left for a follow-up fork-deviation ticket per the plan, since none are introduced by this port.GPT-5.6 Sol audit (three rounds)
Round 1 (
audit-prev.md): 1 BLOCK + 2 WARN — unbounded fallback profile batch (truncation cached as an authoritative miss), the new role line unannounced to assistive technology, no test binding the new fallback-fetch seam. All fixed (commita081bf242/e78130933).Round 2 (
audit-run1.md): 1 BLOCK (discarded — pre-existing shared-hook behavior, not introduced by this diff, and the branch is strictly ahead of upstream on this exact axis) + 5 WARN verified — unbounded role-line length at render, no falsifiable test on the request bound (plus a masked past-window assertion), an uncoveredaboutequality guard, verified provenance excluded from the accessible description, and a doc comment citing the wrong relay clamp number. All 5 fixed (commit72f49a69c).Round 3 (
audit.md): 3 findings, each downgraded from Sol's initial BLOCK rating to WARN after independent reproduction — all three fixed in commitcf7d2bda0:aboutuncapped at the DTO seam — added the 512-byteMENTION_ABOUT_MAX_BYTEScap at the Rust boundary (see Fork deviations above).aboutis known — fixedselectAgentProfileFallbackPubkeysto checkabout === undefinedspecifically (matching the productionmergeAgentNamesIntoProfilesshape, which seeds entries with noaboutkey at all) instead of entry presence, and normalized the pubkey lookup key.aria-describedbyalongside the description and provenance ids.Final state: nothing above NIT remains open against the bar.
Follow-ups
None required to land this port. Left for separate fork-deviation tickets, per the plan's "fork deviations on a ported feature are their own ticket" and as recommended by both the critic and the Sol audit rounds (none are introduced by this diff, all pre-date it on
zs/mainor are inherited unchanged from upstream PR block#2706):buildMentionCandidates.ts'sdescription: user.about ?? nullcollapse permanently excludes search-sourced agents with noaboutin the search row from the users-batch resolve.get_users_batchbelow the relay's 1,000-row clamp, and generation-fencing per-pubkey cache writes infeatures/profile/hooks.ts(a shared hook with ~49 call sites, unchanged by this branch).mentionSuggestionMapping.test.mjs'sagentCandidate→candidatealias is dead indirection kept only to keep ported test bodies byte-identical.Test plan
node --import ./test-loader.mjs --experimental-strip-types --test src/features/messages/lib/mentionSuggestionMapping.test.mjs src/features/messages/ui/MentionAutocomplete.test.mjs src/features/messages/lib/mentionFallbackWindow.test.mjs(fromdesktop/) — 36/36 pass.just fmt-check clippy desktop-check desktop-tauri-clippy file-size-check— clean.cd desktop/src-tauri && cargo test nostr_convert— 77/77 pass, including the 4 new DTO-truncation tests.@-mention picker in a channel with agents whose kind-0 event carries anabout; confirm the role line renders, truncates at 120 graphemes for long bios, and degrades to the literal "agent" label whenaboutis empty. Hover an agent's message to confirm the profile popover still shows the fullabout. Two agents sharing a display name: confirm each row's accessible description (via a screen reader or the browser's accessibility tree inspector) includes its own npub.just ci), not run locally per the ticket instructions.🤖 Generated with Claude Code
https://claude.ai/code/session_01E51uwemNnQ6wdrBWU9EhPE
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.