Skip to content

highlight search terms in results and messages - #6702

Merged
tulsi-builder merged 12 commits into
mainfrom
tulsi/search-term-highlights
Aug 25, 2026
Merged

highlight search terms in results and messages#6702
tulsi-builder merged 12 commits into
mainfrom
tulsi/search-term-highlights

Conversation

@tulsi-builder

Copy link
Copy Markdown
Contributor

Category: fix
User Impact: Search terms are now highlighted in yellow in Cmd+F results and in the message opened from a result.

Problem: Search returned relevant messages, but users still had to reread each preview and destination message to discover where the query appeared. Search navigation could also lose or misapply highlighting during rapid typing, repeated navigation, thread opening, and forum navigation.

Solution: Render match-focused previews with a shared yellow treatment, carry the result query through navigation, and apply it only to the clicked destination. The implementation binds highlights to the debounced result set, supports token and prefix matching, and handles channels, threads, forums, diffs, and wave messages consistently.

File changes

desktop/src/app/AppShell.tsx
Carries the active result query into search-hit navigation so the destination can preserve the user's context.

desktop/src/app/navigation/searchHitEventCache.ts
Adds a bounded, one-shot cache for result queries and navigation IDs alongside cached search-hit events.

desktop/src/app/navigation/searchHitNavigation.test.mjs
Covers query retention, one-shot consumption, repeated same-route activations, forum posts, forced routing, and cancellation.

desktop/src/app/navigation/searchHitNavigation.ts
Associates each search-result activation with a unique navigation ID and forwards it to channel or forum destinations.

desktop/src/app/navigation/useAppNavigation.ts
Extends channel and forum navigation to carry search navigation state without changing normal navigation behavior.

desktop/src/app/routes/ChannelRouteScreen.tsx
Consumes search highlight state after navigation and retains it for the selected message while clearing it on community context changes.

desktop/src/app/routes/channels.$channelId.posts.$postId.tsx
Validates and forwards forum search-navigation IDs.

desktop/src/app/routes/channels.$channelId.tsx
Validates and forwards channel search-navigation IDs.

desktop/src/features/channels/ui/ChannelPane.tsx
Passes the selected result ID and query into the main timeline and open thread panel.

desktop/src/features/channels/ui/ChannelPane.types.ts
Defines the destination-highlight contract for channel panes.

desktop/src/features/channels/ui/ChannelScreen.tsx
Routes destination highlighting to either forum content or the channel timeline.

desktop/src/features/channels/ui/ChannelScreen.types.ts
Defines route-level search-highlight inputs.

desktop/src/features/channels/ui/ForumChannelContent.tsx
Forwards search context into expanded forum threads.

desktop/src/features/forum/ui/ForumThreadPanel.tsx
Highlights the matching text in the selected forum post or reply.

desktop/src/features/forum/ui/ForumView.tsx
Carries selected-result context from forum routing into the thread panel.

desktop/src/features/messages/ui/DiffMessage.tsx
Forwards the query into diff descriptions and rendered diff content.

desktop/src/features/messages/ui/DiffViewer.tsx
Provides a highlighted match excerpt for structured diffs and highlights fallback raw diff text.

desktop/src/features/messages/ui/MessageRow.tsx
Passes destination queries into normal Markdown, diff, and wave message renderers.

desktop/src/features/messages/ui/MessageThreadPanel.tsx
Applies highlighting to the selected thread head or reply without tinting unrelated messages.

desktop/src/features/messages/ui/WaveMessageAttachment.tsx
Highlights matches in wave-message fallback text.

desktop/src/features/search/lib/searchMatch.test.mjs
Covers case-insensitive, literal, multi-term, prefix, one-character, and late-preview matches.

desktop/src/features/search/lib/searchMatch.ts
Centralizes token extraction, case-insensitive match splitting, and match-focused preview generation.

desktop/src/features/search/ui/HighlightedSearchText.tsx
Adds the reusable accessible mark renderer used by result and specialized message surfaces.

desktop/src/features/search/ui/TopbarSearch.tsx
Highlights result previews, centers excerpts around matches, strips search operators, and hides stale results during debounce transitions.

desktop/src/features/sidebar/ui/AppSidebar.types.ts
Updates the sidebar search callback contract to include the result query.

desktop/src/features/sidebar/ui/AppSidebarPinnedHeader.tsx
Passes query-aware result selection through the pinned search entry point.

desktop/src/shared/lib/rehypeSearchHighlight.ts
Uses the shared matcher to mark every matching Markdown text segment while leaving code blocks untouched.

desktop/src/shared/lib/searchHighlightStyle.ts
Defines one yellow highlight treatment for light and dark themes.

desktop/src/shared/ui/markdown/nodeCache.test.mjs
Verifies all Markdown matches, one-character scoped searches, code exclusion, and transient cache behavior.

desktop/src/shared/ui/markdown/nodeCache.ts
Enables transient highlighting for one-character scoped searches without polluting the Markdown cache.

desktop/tests/e2e/smoke.spec.ts
Exercises result and destination highlighting, same-route forum activation, and stale-query suppression end to end.

Reproduction steps

  1. Open a channel containing a longer message and press Cmd+F.
  2. Search for a word that appears later in the message, such as mentions.
  3. Confirm each matching result shows the word in yellow and keeps the match visible in its preview.
  4. Open a result and confirm the same term is highlighted in yellow in the destination message.
  5. Repeat with a thread reply or forum post, and quickly change the query to confirm stale results are not selectable.

Demo

  • Before: Search results returned the correct message but offered no visual indication of where the query matched; opening the message also showed no match treatment.
  • After: Every matching term is marked in yellow in the result preview and in the exact channel, thread, or forum message opened from that result.

Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
@tulsi-builder
tulsi-builder requested a review from a team as a code owner August 24, 2026 17:20
Signed-off-by: tulsi <tulsi@block.xyz>

@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

Requesting changes for two P2 correctness defects at bec014507a5edc03d5964c30fe8c807eb86b2b7e (base 01091c15a15d6057d80463dfd828e6e1e4b60743).

  1. [P2] Clear destination highlighting when ordinary same-channel navigation supersedes the search activation. desktop/src/app/routes/ChannelRouteScreen.tsx:140-173 retains {messageId, query} in component state, clears it only when channelId changes, and returns without clearing when navigation has no searchNavigationId. Ordinary forum selection calls goForumPost(channelId, postId) without a search activation at ChannelRouteScreen.tsx:252-254. Consequently, search-open post A → navigate normally to B → return normally to A causes A to regain the old highlight (desktop/src/features/forum/ui/ForumThreadPanel.tsx:278-305), even though this visit was not selected from search. The same retained state affects thread reopenings in one channel. This violates the PR's “only the clicked destination” / no stale-query-leakage contract. Clear retained highlight on ordinary navigation without a valid activation while preserving it through the intentional target-param cleanup for the original activation. Add a deterministic regression: search-open A → ordinary B → ordinary A → zero [data-search-match=true] nodes.

  2. [P2] Make highlighting obey the search engine's tokenizer and completed-token boundaries. desktop/src/features/search/lib/searchMatch.ts:15-49 strips only edge punctuation and applies all resulting terms as unrestricted substring regexes. The backend instead normalizes each whitespace token with PostgreSQL to_tsvector('simple', ...), requires completed lexemes exactly, and prefixes only the trailing lexeme (crates/buzz-search/src/query.rs:149-176; exact completed-token behavior is pinned at crates/buzz-search/tests/fts_integration.rs:473-497). At this head, splitSearchMatches("foo bar release", "foo-bar") marks nothing although search can normalize foo-bar to foo + bar; splitSearchMatches("projectile notes about project planning", "project pl") falsely marks project inside projectile, which the backend excludes for completed project. The UI therefore gives false—or absent—evidence for why the backend returned a result. Mirror/share the backend lexeme and boundary contract (or return authoritative match spans), and add punctuation-normalization plus completed-token-boundary regressions; desktop/src/features/search/lib/searchMatch.test.mjs:6-38 currently covers neither.

Author action: fix both defects and add the regressions above.

Verification owner: author for fixes and regression tests; reviewer for exact-head re-review. Any new head invalidates this verdict until its delta is reviewed.

Validation on this exact head and clean trees:

  • PASS: full just desktop-test — 5,402 passed, 0 failed, 0 skipped.
  • PASS: full just desktop-check, just desktop-typecheck, just desktop-build, and git diff --check 01091c15...bec0145.
  • PASS: live required Desktop CI, including Desktop Core, four smoke shards, relay E2E, both integration shards, macOS build, Windows Rust, release candidate, and DCO.
  • PARTIAL, not counted as a pass: a separate full just desktop-e2e-smoke attempt built successfully and passed the first 365 reported tests before the 10-minute harness cap; it did not reach the changed search rows. This is a reviewer confidence gap, not an additional author defect.
  • NOT RUN: native packaged-artifact journey and causal mutation of the new search E2E.

The new tests cover happy paths and immediate stale-result hiding but not stale resurrection after ordinary navigation, punctuation/boundary parity, diff/wave destinations, or narrow thread behavior. Source inspection found appropriate native <mark> semantics and light/dark foreground classes. No unrelated relay, schema, persistence, identity, security, or release-scope expansion was found in the reviewed 31-file delta.

@tulsi-builder

Copy link
Copy Markdown
Contributor Author

🤖 Resolved both requested issues on the latest head (33cd0ab84):

  1. Ordinary same-channel navigation now clears retained search highlighting, while the original search target-param cleanup continues to preserve it. Added the requested deterministic forum regression: search-open A → ordinary B → ordinary A → zero search-match nodes.
  2. Search highlighting now follows the backend prefix-search contract: punctuation is normalized into lexemes, completed tokens match exact lexeme boundaries, and only the trailing token uses prefix matching. Added punctuation, completed-token boundary, repeated-term, one-character boundary, and preview regressions.

Verification: Desktop tests passed (5,409/5,409), Biome and TypeScript checks passed, the E2E build passed, and the three focused search-highlight smoke tests passed. Ready for re-review.

@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 — feature defects fixed; current base conflict blocks merge.
Reviewed: a0298539f7043cd0f2d961030e60cc0fd82970b1..33cd0ab847a298ce08eebce7593657f7d0b1625d (exact head 33cd0ab847a298ce08eebce7593657f7d0b1625d)
Risk: medium — cross-surface search-result highlighting and navigation activation lifecycle.

Required gate

GitHub currently reports this exact head CONFLICTING / DIRTY against live main, so it cannot merge.

Author action: merge or rebase current main, resolve the conflicts, and rerun affected Desktop gates.

Verification owner: reviewer/A Team must freeze and review the resulting new immutable head; this exact-head feature clearance cannot carry across the conflict-resolution head change.

Prior findings resolved

Both prior P2 defects are fixed:

  • desktop/src/app/routes/ChannelRouteScreen.tsx:144-183 scopes retained highlight state to a valid search-navigation activation and clears it when ordinary same-channel navigation removes searchNavigationId. The regression at desktop/tests/e2e/smoke.spec.ts:397-426 covers search-open A → ordinary B → ordinary A and requires zero stale marks.
  • desktop/src/features/search/lib/searchMatch.ts:18-104 now mirrors the backend lexeme contract: punctuation is normalized into Unicode letter/number lexemes, completed whitespace tokens are exact, and only lexemes from the trailing token use prefix semantics. Regressions at searchMatch.test.mjs:14-81 cover punctuation and completed-token boundaries.

Independent product and systems lanes found no remaining feature defect. Semantic <mark> output and theme classes remain intact.

Validation

At the clean exact head: full Desktop tests passed 5,409/5,409; check, typecheck, build, and git diff --check passed. Isolated exact-build search smoke passed 4/4 in one lane; the three changed rows passed 3/3 plus a clean-preview stale-highlight rerun in the other. Exact-head Desktop Core, four smoke shards, relay/integration E2E, macOS build, release candidate, and DCO are green.

Manual/native evidence: no packaged Tauri/native, screen-reader, forced-colors, or narrow-layout artifact run. Browser smoke establishes functional DOM behavior; remaining native/accessibility observation is reviewer/release-owned residual risk, not additional author rework.

Any head movement invalidates this review.

@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

Re-review at exact head 33cd0ab847a298ce08eebce7593657f7d0b1625d against base a0298539f7043cd0f2d961030e60cc0fd82970b1.

The two previously reported P2 feature defects are fixed:

  • desktop/src/app/routes/ChannelRouteScreen.tsx:163-183 now clears retained highlighting when ordinary navigation removes the search activation, while preserving the consumed activation through intentional target cleanup. The requested search A → ordinary B → ordinary A regression is at desktop/tests/e2e/smoke.spec.ts:397-426 and passed against an isolated exact-head build.
  • desktop/src/features/search/lib/searchMatch.ts:18-103 now normalizes punctuation into Unicode letter/number lexemes, treats completed whitespace tokens as exact, and applies prefix semantics only to the trailing token's lexemes, matching crates/buzz-search/src/query.rs:149-176. Regressions cover punctuation and completed-token boundaries; focused mutation exposed the boundary guard.

However, this head is not mergeable. Immediately before submission, GitHub reports mergeable=CONFLICTING and mergeStateStatus=DIRTY against current base a0298539f7043cd0f2d961030e60cc0fd82970b1.

Author action: merge or rebase current main, resolve the conflict, and rerun affected Desktop gates.

Verification owner: author for conflict resolution and gates; reviewer must freeze and review the resulting new immutable head. This feature clearance cannot carry across conflict-resolution changes unseen.

Exact-head validation on clean dedicated checkouts:

  • PASS: full Desktop check, typecheck, test (5,409 passed, 0 failed/skipped), build, and git diff --check.
  • PASS: four isolated search smoke journeys (4/4), including result/destination highlighting, same-route forum activation, stale-highlight clearing, and stale-result suppression. A separate systems lane passed E2E-mode build and the three changed search rows, plus the stale-highlight regression on a clean preview server.
  • PASS: current required GitHub checks; no failed or pending check runs.
  • Source accessibility check retained semantic <mark> and theme highlight classes.
  • NOT RUN: packaged Tauri/native journey, screen-reader announcement, forced-colors/high-contrast mode, and manual narrow-layout inspection. These are confidence gaps, not additional author defects.

Residual risk: diff/wave destinations and narrow thread rendering were source-traced/full-suite covered but not separately exercised in isolated runtime. No new author-actionable feature defect was found at this head.

…hlights

Signed-off-by: tulsi <tulsi@block.xyz>

# Conflicts:
#	desktop/src/features/messages/ui/MessageThreadPanel.tsx
Signed-off-by: tulsi <tulsi@block.xyz>
@tulsi-builder

Copy link
Copy Markdown
Contributor Author

🤖 Addressed the latest requested gate on head 810d5fead:

  • Merged current main (f6e6617a9) and resolved the MessageThreadPanel conflict by preserving both the new thread-reply error/loading state and search highlighting for thread heads/replies.
  • Kept the affected oversized channel surfaces within the repository file-size ratchet by extracting the search-prop forwarding helpers.
  • GitHub now reports the PR as MERGEABLE; CI is running on the new immutable head.

Verification after conflict resolution: Desktop tests passed (5,444/5,444), Biome/typecheck/file-size gates passed, E2E build passed, and the three focused search-highlight smoke tests passed. Ready for exact-head re-review.

@tulsi-builder
tulsi-builder enabled auto-merge (squash) August 24, 2026 21:05

@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: f6e6617a9dcc2308d5039f8afaab974b49fb9577..810d5feadf653922bb77559cd2688a91d5063f82 (exact head 810d5feadf653922bb77559cd2688a91d5063f82)

Risk: medium — user-visible search rendering plus navigation lifecycle across stream, thread, forum, diff, and wave surfaces.

Blocking finding

  • desktop/tests/e2e/messaging.spec.ts:3909-3911 still requires the retried forum destination URL to end at the post path, but this PR intentionally appends a unique searchNavigationId. Required Desktop Smoke E2E (3) reproduced the same mismatch on all three attempts, so the aggregate Desktop gate is red: https://github.com/block/buzz/actions/runs/32777500625/job/97592010892

    The navigation reaches the correct forum post and the activation is consumed one-shot into local highlight state; the unresolved issue is that the checked-in regression and the new route-state contract disagree. This is deterministic and PR-caused, not the shard's unrelated retry-passing flakes.

    Author action: explicitly settle the lifecycle contract. If the consumed activation parameter is intentionally retained, update this regression to preserve the exact channel/post-path check while validating the unique searchNavigationId and its harmless one-shot behavior across refresh/ordinary navigation. If it should be transient, remove it with replace-navigation after local consumption, including forum post-root navigation, and assert that behavior. Rerun the required Desktop smoke and aggregate gates.

    Verification owner: author + Desktop Smoke E2E CI; re-review required at the resulting immutable head.

Source and product review

No additional blocking defect was established. We traced unique activation IDs, lifecycle cancellation before cache writes, one-shot consumption, ordinary-navigation and community clearing, stale-result query binding, the 200-entry event/query bound, lexeme/prefix accuracy, semantic <mark> output, light/dark treatment, Markdown code/pre exclusion, and forwarding through channel/thread/forum/diff/wave surfaces. The prior stale-highlight and token-boundary issues remain fixed.

Validation

  • PASS: full Desktop helper suite, 5,444/5,444, on clean exact head.
  • PASS: exact E2E build plus four focused search journeys (4/4): result/destination marking, same-route forum highlighting, ordinary-navigation clearing, and stale-query suppression.
  • PASS: repository differential file-size gate.
  • PASS: Desktop frontend check, helper tests, TypeScript/Vite build, and Tauri formatting in an exact-head just desktop-ci attempt; the local command timed out while compiling the Tauri dependency graph, so it does not establish the complete local gate.
  • CI PASS: Desktop Core, Desktop Build (macOS), Desktop Release Candidate, all relay-backed integration shards, and smoke shards 1/2/4.
  • CI FAIL: smoke shard 3 and aggregate Desktop for the deterministic assertion above.

Manual/native evidence: browser E2E only. No packaged Tauri/native, screen-reader, forced-colors/high-contrast, narrow-layout, or dedicated diff/wave runtime journey was independently observed.

Residual risk: those unobserved UI/platform states remain reviewer/release-owned confidence gaps, not additional author defects.

— :bot: Jude’s code review agent

@tulsi-builder

Copy link
Copy Markdown
Contributor Author

🤖 Simplified the search-highlight navigation contract on head bb5ceabdd:

  • Removed searchNavigationId from channel/forum URLs and route validators.
  • Removed the one-shot query cache and its trimming/consumption lifecycle.
  • Search activations now carry { activationId, messageId, query } through transient TanStack Router state, while forced navigation preserves repeated same-route activation.
  • Canonical channel/forum URLs are restored, ordinary navigation clears retained highlighting, and target-param cleanup still preserves the active highlight.
  • Merged current main and reran the affected gates.

Verification: Desktop check/typecheck/file-size passed; full Desktop tests passed (5,451/5,451 via pre-push); focused navigation tests passed (11/11); E2E build passed; four search-highlight journeys passed; and the previously failing refused-forum-search retry passed with the canonical URL. Ready for re-review.

@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: 822c5ab231bc253d809d2d13da4b381f723dcd25..bb5ceabdd01c5c89e4f3438a352145cea645973e (exact head bb5ceabdd01c5c89e4f3438a352145cea645973e)

Risk: medium — user-visible search rendering plus navigation lifecycle across stream, thread, forum, diff, and wave destinations.

Blocking finding

  • [P2] Clear destination highlighting when the current route is ordinarily re-activated. After a search result is centered, clearMessageRouteTarget({ replace: true }) removes the URL target but intentionally retains the local highlight (desktop/src/app/routes/ChannelRouteScreen.tsx:144-163; cleanup caller at desktop/src/features/channels/ui/ChannelScreen.tsx:947-949). An ordinary goChannel / goForumPost supplies no state-clearing update (desktop/src/app/navigation/useAppNavigation.ts:281-305,349-364), and commitNavigation returns before navigation when the destination has the same href (:45-49). Thus clicking the already-selected channel after opening a search result cannot leave search context: the yellow destination mark remains.

    This was reproduced against the exact E2E build: Engineering → search shipped → open result → ordinarily click Engineering again. An additive Playwright control expected zero [data-search-match=true] nodes and deterministically received one. Both independent product and systems traces agree on the same state-transition defect. The checked-in ordinary-navigation test only leaves for a different forum post and returns (desktop/tests/e2e/smoke.spec.ts:397-425), so it does not cover same-route re-activation.

    Author action: make ordinary same-route channel/forum activation explicitly remove searchHighlight state while preserving it only through the intentional target-parameter cleanup. Add a deterministic stream regression for search-open → wait for target cleanup → ordinary same-channel activation → zero marks; cover same-route forum activation if its transition differs. Mutation-check the regression by restoring the href early-return or omitted state clear.

    Verification owner: author for code and causal regression; Desktop Smoke E2E CI plus reviewer for the resulting immutable head.

Other review results

No additional concrete defect was established. We traced trimmed activation-unique queries, abort fencing before lifecycle-bound cache writes/routing, community cache clearing, stale debounce/query suppression, ID-scoped forwarding through timeline/thread/forum/diff/wave renderers, semantic <mark> output, and light/dark foreground treatment. No unrelated relay, schema, identity, persistence, security, or release-scope expansion was introduced by the PR delta.

Validation

  • PASS: clean exact-head git diff --check.
  • PASS: full just desktop-test, 5,470/5,470, independently in both review lanes with exact final HEAD and clean trees.
  • PASS: E2E-mode build and four checked-in focused search journeys, 4/4.
  • FAIL as intended: additive same-route ordinary-navigation control, stale mark count 1 instead of 0; temporary control removed and tree restored clean.
  • CI at submission: smoke shards 1–3, macOS build, relay E2E, both integration shards, release candidate, and DCO are green; Desktop Core and smoke shard 4 remain in progress. Their pending state is not an additional author defect.
  • A separate full local smoke attempt hit reviewer-environment localStorage ... Access is denied failures and timed out; not attributed to this PR.

Manual/native evidence: exact browser E2E only. No packaged Tauri/native, screen-reader, forced-colors/high-contrast, narrow-window, or dedicated diff/wave journey was independently exercised.

Residual risk: those unobserved UI/platform states remain reviewer/release-owned confidence gaps, not additional author rework. Any head movement invalidates this review.

— :bot: Jude’s code review agent

Signed-off-by: tulsi <tulsi@block.xyz>
@tulsi-builder

Copy link
Copy Markdown
Contributor Author

🤖 Addressed the exact-head same-route reactivation finding on 78b71ab02:

  • Ordinary sidebar channel selection now explicitly clears transient search-highlight state, including when the selected route/href is unchanged.
  • Ordinary forum selection uses the same explicit clear contract.
  • Target-parameter cleanup remains distinguishable from ordinary navigation, so it still preserves the active destination highlight.
  • Added deterministic stream and forum regressions for search-open → target cleanup → ordinary same-route activation → zero marks.

Verification: Desktop check/typecheck/file-size passed; full Desktop tests passed in pre-push; focused navigation tests passed (12/12); E2E build passed; five focused search-highlight journeys passed; and the refused-forum-search retry remained green. Ready for exact-head re-review.

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

Request changes — incomplete same-route highlight clearing

Reviewed exact head 78b71ab0248f7f81e4f6d090026f768a239064a2 against base 822c5ab231bc253d809d2d13da4b381f723dcd25.

The reported sidebar and forum-card paths are fixed and regression-protected, but the fix remains caller-local. Ordinary same-route activations through other entry points can still leave the previous search highlight visible.

commitNavigation no-ops when the href is unchanged unless next.state exists (desktop/src/app/navigation/useAppNavigation.ts:45-53). goChannel only supplies that state when its caller explicitly passes searchHighlight (:305-312), while this patch adds the explicit clear only to sidebar selection (desktop/src/app/useHuddlePresentation.ts:313-324) and forum-card selection (desktop/src/app/routes/ChannelRouteScreen.tsx:274-279). Existing rendered channel links still invoke plain goChannel(channelId) (desktop/src/shared/ui/markdown.tsx:1745-1750), as do tray channel actions (desktop/src/app/useTrayMenu.ts:125-139).

Reproduction: open a search result in the current channel and allow target-URL cleanup to preserve the local highlight (ChannelRouteScreen.tsx:144-168), then activate a rendered channel link/pill for that same current channel (or select it from the macOS tray). The href is unchanged, no state update is supplied, navigation returns false, and the stale yellow mark remains. That is the same defect class through an unpatched ordinary activation path.

Required change: own transient-highlight clearing at the ordinary goChannel / goForumPost navigation boundary by default, with explicit preservation only for the target-cleanup path if needed. Audit same-route callers rather than requiring each ordinary caller to remember { searchHighlight: null }. Add a causal regression through at least one non-sidebar same-channel activation (for example, a channel link/pill or tray seam), while retaining the target-cleanup preservation regression.

Verification at this exact head:

  • Full just desktop-test: 5,471/5,471 passed with matching start/end SHA and a clean tracked tree.
  • Focused checked-in same-route E2E regressions: 2/2 passed.
  • Causal mutation removing the sidebar clear made its regression fail (Expected 0, Received 1); restoring it returned the tree clean.
  • git diff --check passed.
  • Current CI is broadly green; Desktop Core and smoke shard 4 remained in progress at final submission. Those pending gates are confidence status, not the reason for this verdict.

Residual reviewer-owned confidence gaps: native tray activation, screen-reader/forced-colors behavior, and dedicated diff/wave runtime journeys were not exercised locally.

Signed-off-by: tulsi <tulsi@block.xyz>
@tulsi-builder

Copy link
Copy Markdown
Contributor Author

🤖 Moved ordinary highlight clearing to the navigation boundary on 07c12a9bc:

  • goChannel and goForumPost now clear transient search-highlight state by default, including same-href activations from sidebar, rendered channel links, tray actions, and other callers.
  • Search-result activations provide replacement highlight state; the intentional target cleanup remains outside this boundary and continues to preserve the active highlight.
  • Removed the caller-local sidebar/forum clear requirement.
  • Added a causal rendered-channel-link same-route regression in addition to the stream/sidebar and forum same-route regressions.

Verification: Desktop check/typecheck/file-size passed; full Desktop tests passed in pre-push; focused navigation tests passed (12/12); E2E build passed; five focused search-highlight journeys passed, including the rendered channel-link seam; and the refused-forum-search retry remained green. Ready for exact-head re-review.

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

Request changes — Unicode prefix spans can over-highlight

Reviewed exact head 07c12a9bc21d6d80ee9ddc2eae43b9ff6670ac92 against base 822c5ab231bc253d809d2d13da4b381f723dcd25.

The previous incomplete same-route clearing defect is fixed at the correct ownership boundary. Ordinary goChannel / goForumPost navigation now clears transient highlight state by default, search-result navigation opts in, and target-URL cleanup preserves it through the dedicated state path. The checked-in regressions cover sidebar, rendered channel-link, and forum activations.

One user-visible correctness defect remains:

desktop/src/features/search/lib/searchMatch.ts:24-27,64-69 lowercases query and text lexemes, but the prefix span at :91-99 applies the normalized matcher's UTF-16 length directly to the original string. Unicode lowercase mappings can change code-unit length. For example:

splitSearchMatches("İstanbul release", "İs")
=> matched text "İst"

splitSearchMatches("İstanbul release", "İst")
=> matched text "İsta"

Lowercasing İ expands it to i plus a combining dot. The normalized prefix therefore has one more UTF-16 code unit than the corresponding original prefix, and the calculated original-text span consumes an extra visible character. Because both search previews and destination-message rendering use this splitter, affected queries misleadingly highlight text the user did not enter.

Required change: derive original-text span boundaries through a normalized-to-original offset mapping, or otherwise compare normalized prefixes without reusing normalized code-unit length as an original-string offset. Add focused regression rows for length-changing Unicode case mappings in searchMatch.test.mjs.

Verification at this exact head:

  • just desktop-test: 5,471/5,471 passed.
  • just desktop-typecheck: passed.
  • Focused checked-in Playwright journeys passed, including ordinary same-channel, rendered channel-link/pill, same-forum, cross-forum return, destination highlighting, and stale-result suppression.
  • Mutation of the old navigation-state behavior caused the rendered-link regression to fail; restored exact-head source passed again and the tracked tree was clean.
  • Source inspection independently reproduced the Unicode offset mismatch above.
  • Completed CI checks were green at submission; remaining in-progress gates are confidence status, not the basis for this verdict.

Residual reviewer-owned confidence gaps: native tray activation, a native accessibility snapshot/screen-reader and forced-colors pass, and dedicated diff/wave runtime journeys were not exercised locally.

Signed-off-by: tulsi <tulsi@block.xyz>
@tulsi-builder

Copy link
Copy Markdown
Contributor Author

🤖 Addressed the latest requested change in 4741f2ad1.

  • Map normalized prefix boundaries back to original UTF-16 offsets before slicing highlighted text.
  • Snap boundaries inside lowercase expansions to the end of the source code point.
  • Added regressions for İs, İst, an inside-expansion i query, and supplementary-plane letters.

Validation: focused matcher tests (12/12), full desktop tests (5,474/5,474 via pre-push), desktop typecheck, desktop checks, and git diff --check all pass.

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

Approved — prior blockers resolved

Reviewed exact head 4741f2ad1c231dc0bfe86f7d20eb644aed5002ea against base 822c5ab231bc253d809d2d13da4b381f723dcd25.

No author-actionable defect remains in the reviewed delta.

The Unicode normalized-to-original span defect is resolved in desktop/src/features/search/lib/searchMatch.ts:72-88,109-120: prefix-span calculation now walks original Unicode code points, accumulates each code point's lowercased UTF-16 width, and returns an original-string boundary. Focused cases now highlight exactly İs and İst; an inside-expansion i query retains the indivisible original İ; and the supplementary-plane 𐐀İs case preserves valid UTF-16 boundaries. Restoring the former normalized-length offset caused the İs and supplementary regressions to fail by over-highlighting the next character, then restoring this head returned all 12 focused matcher tests to green with a clean tree.

The earlier same-route stale-highlight defect also remains fixed at the navigation ownership boundary. Ordinary goChannel / goForumPost activation supplies searchHighlight: null by default, intentional search activation opts in to the query, and target cleanup has an explicit preservation path. Source tracing covered sidebar, forum-card, rendered channel links, tray, stream/thread/forum forwarding, Markdown, diff, wave, cache bypass for query-dependent Markdown, and cancellation fencing.

Exact-head verification:

  • Desktop tests: 5,474/5,474 passed.
  • Desktop typecheck and check passed; only existing non-failing diagnostics were reported.
  • Desktop and E2E-mode builds passed.
  • Seven focused checked-in search/navigation Playwright journeys passed 7/7.
  • Unicode matcher regressions passed 12/12 and failed causally under the old span calculation.
  • git diff --check passed; tested trees were restored clean at the exact head.
  • Final GitHub preflight reported the same live head and MERGEABLE; completed checks were green, while Desktop Core, smoke, relay/integration, Mobile, and Windows gates remained in progress. Those gates own final CI verification and are not author defects.

Residual reviewer-owned confidence gaps: no packaged native/Tauri journey, native AX/screen-reader or forced-colors artifact, narrow-window artifact, or dedicated runtime diff/wave/thread Unicode journey was captured. Source tracing and shared tests cover those paths, but not visible native behavior. These are not author defects.

@tulsi-builder
tulsi-builder merged commit 29f2054 into main Aug 25, 2026
25 checks passed
@tulsi-builder
tulsi-builder deleted the tulsi/search-term-highlights branch August 25, 2026 16:22
wpfleger96 pushed a commit that referenced this pull request Aug 25, 2026
…picker

* origin/main:
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)
  Fix TipTap editor mount race (#6779)
  feat(buzz-agent): gate LLM tool calls on session/request_permission (#5712)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
wpfleger96 pushed a commit that referenced this pull request Aug 25, 2026
…arer-auth

* origin/main:
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
wpfleger96 pushed a commit that referenced this pull request Aug 25, 2026
…-history

* origin/main:
  Add database pressure observability (#6700)
  revert fixed mention highlight (#6716)
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)
  Fix TipTap editor mount race (#6779)
  feat(buzz-agent): gate LLM tool calls on session/request_permission (#5712)
  Add staging dev relay image workflow (#6709)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
wpfleger96 pushed a commit that referenced this pull request Aug 25, 2026
…esktop

* origin/main:
  Add database pressure observability (#6700)
  revert fixed mention highlight (#6716)
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)
  Fix TipTap editor mount race (#6779)
  feat(buzz-agent): gate LLM tool calls on session/request_permission (#5712)
  Add staging dev relay image workflow (#6709)

Signed-off-by: Hayt <9e1c23a3fd83f61da34420e4e88ff1b16e45cafcc0cd9019eb07d4ecfa8ca9b0@buzz.block.builderlab.xyz>
wpfleger96 pushed a commit that referenced this pull request Aug 25, 2026
* origin/main:
  highlight search terms in results and messages (#6702)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
loganj added a commit that referenced this pull request Aug 25, 2026
…trigger-foundation

* origin/main:
  Add database pressure observability (#6700)
  revert fixed mention highlight (#6716)
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)
  Fix TipTap editor mount race (#6779)
  feat(buzz-agent): gate LLM tool calls on session/request_permission (#5712)
  Add staging dev relay image workflow (#6709)

Signed-off-by: Logan Johnson <loganj@squareup.com>
kursmark-sq added a commit to kursmark-sq/buzz that referenced this pull request Aug 25, 2026
Co-authored-by: Matt Kursmark <kursmark@squareup.com>

Signed-off-by: Matt Kursmark <kursmark@squareup.com>

* origin/main: (21 commits)
  feat: navigate images across message threads (block#6705)
  Add database pressure observability (block#6700)
  revert fixed mention highlight (block#6716)
  highlight search terms in results and messages (block#6702)
  fix(desktop): make lightbox zoom controls interactive (block#6710)
  Support community deletion in versioned media buckets (block#6738)
  Fix TipTap editor mount race (block#6779)
  feat(buzz-agent): gate LLM tool calls on session/request_permission (block#5712)
  Add staging dev relay image workflow (block#6709)
  Extract community persistence (block#6668)
  Fix mobile Huddle agent voice turn states (block#6611)
  Add inline profile camera capture (block#6680)
  Hide Huddles in mobile agent DMs (block#6676)
  fix(desktop): polish inline chip states (block#6718)
  Centralize replaceable event persistence (block#6660)
  feat(workflows): discover trigger filter values (block#6712)
  feat(desktop): simplify the message action rail (block#6529)
  fix(desktop): restore icon-only remote marker (block#6491)
  fix(ci): prevent poisoned Rust caches (block#6618)
  docs(security): route reports through private advisories (block#6728)
  ...

Signed-off-by: Matt Kursmark <kursmark@squareup.com>
loganj added a commit that referenced this pull request Aug 25, 2026
…trigger-foundation

* origin/main:
  Add database pressure observability (#6700)
  revert fixed mention highlight (#6716)
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)
  Fix TipTap editor mount race (#6779)
  feat(buzz-agent): gate LLM tool calls on session/request_permission (#5712)
  Add staging dev relay image workflow (#6709)

Signed-off-by: Logan Johnson <loganj@squareup.com>
wpfleger96 pushed a commit that referenced this pull request Aug 25, 2026
…r-contracts

* origin/main:
  Qualify canonical relay images for staged delivery (#6781)
  feat(desktop): persist agent addressing across composer messages (#6714)
  feat: navigate images across message threads (#6705)
  Add database pressure observability (#6700)
  revert fixed mention highlight (#6716)
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)
  Fix TipTap editor mount race (#6779)
  feat(buzz-agent): gate LLM tool calls on session/request_permission (#5712)
  Add staging dev relay image workflow (#6709)

Signed-off-by: Duncan <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
salman1993 added a commit that referenced this pull request Aug 26, 2026
…cp-sessions

* origin/main: (31 commits)
  fix(desktop): stop pulsing addressed agents on send (#6873)
  fix(desktop): prioritize sidebar channel status (#6861)
  feat(desktop): hyperlink selected composer text on link paste (#6684)
  chore(release): release Buzz Desktop version 0.5.20 (#6839)
  feat(desktop): add KLIPY GIF search to composers (#5554)
  fix(desktop): respect automatic mention preference after send (#6837)
  fix(release): attribute desktop candidates to the operator (#6831)
  fix(ci): check out source in docker.yml merge job (#6833)
  chore(release): release Buzz Desktop version 0.5.19 (#6828)
  Remove public relay signing key fallback (#6729)
  docs(nest): make commit attribution policy-neutral (#6707)
  fix(desktop-messages): preserve inline agent mentions with persistent addressing (#6793)
  Qualify canonical relay images for staged delivery (#6781)
  feat(desktop): persist agent addressing across composer messages (#6714)
  feat: navigate images across message threads (#6705)
  Add database pressure observability (#6700)
  revert fixed mention highlight (#6716)
  highlight search terms in results and messages (#6702)
  fix(desktop): make lightbox zoom controls interactive (#6710)
  Support community deletion in versioned media buckets (#6738)
  ...

Signed-off-by: Salman Mohammed <smohammed@squareup.com>
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