Skip to content

Prioritize full command palette title matches - #6498

Merged
lawrencecchen merged 2 commits into
mainfrom
task-prioritize-full-search-matches
Jun 20, 2026
Merged

lawrencecchen merged 2 commits into
mainfrom
task-prioritize-full-search-matches

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Jun 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Prioritize command-palette results whose visible title words exactly match or prefix-match the query, even when the title starts with an emoji/symbol badge.
  • Keep Swift fallback and Nucleo FFI ranking semantics aligned.
  • Add regression coverage for emoji-prefixed full-title and prefix-title ordering.

Testing

  • swift test --filter CommandPaletteSearchEngineTests/searchPrefersEmojiPrefixedFullTitleWordsOverPartialTitlePrefix (red before fix, green after fix)
  • swift test --filter CommandPaletteSearchEngineTests/optimizedSearchMatchesReferencePipeline
  • swift test
  • cargo fmt --check && cargo test && cargo build --release (Native/CommandPaletteNucleoFFI)
  • /Users/lawrence/fun/cmuxterm-hq/skills/autoreview/scripts/autoreview --mode branch --base origin/main
  • ./scripts/reload-cloud.sh --tag sort
  • UI preflight in tagged app: Cmd+P, query command palette, verified Command Palette ranks above Command Palette Archive

Issues

  • Task: user reported bad command-palette sorting order and suspected emoji/full-match priority.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Note

Low Risk
Localized search-ranking changes with dual-path parity tests; no auth, data, or network surface—only Cmd+P result ordering.

Overview
Command palette ranking now treats visible title words (alphanumeric segments only, dropping emoji/symbol-only chunks) as a first-class match target, so queries like command palette prefer 🧪 Command Palette over Command Palette Archive or rows that only hit hidden keywords.

Swift: Corpus entries precompute normalizedTitleSearchWordText; PreparedQuery adds normalizedTokenText (tokens joined with single spaces). CommandPaletteSearchEngine takes the max of fuzzy score, title fuzzy + bonus, and a new title-word exact/prefix tier keyed off normalizedTokenText (including repeated spaces in the query). Shared helper commandPaletteNormalizedSearchWordText mirrors the Rust word extraction.

Rust (Nucleo FFI): Each candidate stores search_title from the same word-stripping logic; title_literal_score applies exact/prefix atom checks against search_title when the raw title does not match.

Reference scoring and regression tests cover Swift engine, Nucleo FFI, and emoji-prefixed / hidden-token ordering cases.

Reviewed by Cursor Bugbot for commit 15fd564. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Prioritize command palette results whose visible title words exactly or prefix-match the query, including emoji-prefixed titles. Full-title matches now outrank partial title prefixes and hidden keyword hits across Swift and Nucleo FFI.

  • Bug Fixes
    • Normalize title “search-word” text by dropping symbol-only segments; store as normalizedTitleSearchWordText in Swift and search_title in Rust; use it for exact/prefix title tiers.
    • Scoring now takes the max of: fuzzy score; title literal score + a scaled per-token bonus; and a new exact/prefix match on normalized title-word text via PreparedQuery.normalizedTokenText (handles repeated spaces).
    • Keep Swift, Nucleo FFI, and a reference scorer aligned; add regression tests for emoji-prefixed full/prefix matches, repeated-space queries, and cross-FFI ordering.

Written for commit 15fd564. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

Release Notes

  • New Features
    • Improved command palette search ranking by boosting matches against normalized title “word” text (including exact and prefix tiers).
    • Enhanced emoji-aware title search so emoji-prefixed titles are prioritized over partial/hidden-token matches.
  • Tests
    • Added/expanded unit and Nucleo-backed test coverage to verify the updated title-word and emoji-aware ranking behavior.

@vercel

vercel Bot commented Jun 20, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Canceled Canceled Jun 20, 2026 11:12am

@coderabbitai

coderabbitai Bot commented Jun 20, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a word-normalized title representation (search_title in Rust, normalizedSearchWordText in Swift) to the candidate model, strips symbol-only segments (e.g., emoji prefixes), and extends literal and weighted scoring in both the Rust FFI and Swift layers to match against this derived field. New tests assert that emoji-prefixed title-word matches rank above partial or hidden-token alternatives.

Changes

Search Word Normalization and Emoji-Prefixed Title Ranking

Layer / File(s) Summary
Word normalization data model and extraction helpers
Native/CommandPaletteNucleoFFI/src/lib.rs, Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchWordText.swift
Adds search_title: String field to Rust Candidate struct. Implements title_search_word_text and append_search_word (Rust) to split titles on word boundaries and accumulate alphanumeric segments. Implements commandPaletteNormalizedSearchWordText and commandPaletteContainsSearchWordScalar (Swift) to extract and filter word segments by Unicode alphanumeric content.
Rust FFI: Indexing and scoring with normalized titles
Native/CommandPaletteNucleoFFI/src/lib.rs
During index creation, search_title is computed from the loaded title and stored in Candidate. Extends title_literal_score to check search_title for exact and prefix literal matches. Adjusts weighted_query_score formatting.
Swift: Weighted score with title-word matching
Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchEngine.swift, Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swift
Expands weightedScore from a two-way to a three-way max including commandPaletteTitleWordScore. Adds commandPaletteScaledTitleMatchBonus and refactors FuzzyMatcher initializers for clarity.
Test infrastructure mirroring production scoring
Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchReferenceScoring.swift, Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchEngineTests.swift
Adds commandPaletteWeightedReferenceScore and commandPaletteTitleWordReferenceScore replicating production scoring logic. Updates referenceResults to call the new shared reference function with explicit parameters, removing the local weightedReferenceScore helper.
Emoji-prefixed title ranking validation tests
Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteEmojiTitleSearchTests.swift
Adds four tests: two pure Swift unit tests asserting that optimizedResults ranks emoji-prefixed full-title-word and prefix-title-word matches above partial or hidden-token alternatives; two conditionally-run Nucleo FFI integration tests verifying the same ranking via NucleoIndex.search.

Sequence Diagram

sequenceDiagram
  participant IndexInit as Index Creation
  participant SearchFn as Word Extraction
  participant Candidate
  participant Scorer as Scoring Engine
  participant FuzzyMatcher as Fuzzy Matcher
  participant TitleWordScore as Title Word Score
  participant Result as Ranked Results

  IndexInit->>SearchFn: Extract words from title
  SearchFn-->>Candidate: Store search_title (alphanumeric words)
  
  FuzzyMatcher->>Scorer: Prepared query
  Scorer->>FuzzyMatcher: Score fuzzy matches
  Scorer->>TitleWordScore: Normalize title word text
  TitleWordScore->>TitleWordScore: Match exact or prefix
  TitleWordScore-->>Scorer: Award token + scaled bonus
  Scorer->>Scorer: max(fuzzyScore, titleScore, wordScore)
  Scorer-->>Result: Highest-scoring entries first
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • manaflow-ai/cmux#5148: Modifies the same title_literal_score function in Native/CommandPaletteNucleoFFI/src/lib.rs, adding whole-query title-literal exact/prefix tier logic in weighted_query_score — directly adjacent to the scoring paths extended in this PR.

Poem

🐇 A bunny hops through title words one by one,
Skipping the 🌟 emoji, just keeping the fun.
"search me," says the title, "by letters alone!"
The score climbs the highest for words that are known.
Now emoji-crowned entries leap right to the top —
The fuzzy match hops on and never will stop! 🥕

🚥 Pre-merge checks | ✅ 23
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Prioritize full command palette title matches' accurately summarizes the main change—improving search ranking to favor exact and prefix matches on visible title words, which is the core objective of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 80.95% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed All Swift production changes maintain proper Sendable declarations on value types and introduce only pure helper functions with no actor isolation violations or MainActor contamination.
Cmux Swift Blocking Runtime ✅ Passed PR adds only pure computational logic for search ranking (string normalization, score calculation). No blocking primitives, timers, sleeps, locks, or synchronization constructs introduced in Swift...
Cmux Expensive Synchronous Load ✅ Passed This PR makes purely algorithmic improvements to command palette search ranking through string normalization and scoring logic with no expensive synchronous I/O, system calls, or additions of Resto...
Cmux Cache Substitution Correctness ✅ Passed PR adds precomputed derived fields (normalizedTitleSearchWordText in Swift, search_title in Rust) computed once at index/entry initialization, not cached values replacing fresh reads. No persistenc...
Cmux No Hacky Sleeps ✅ Passed PR contains no changes to TypeScript, JavaScript, shell, or build/runtime scripts. Changes are exclusively in Rust and Swift, which are not subject to the runtime-no-hacky-sleeps rule.
Cmux Algorithmic Complexity ✅ Passed The PR computes normalized search-word text once per entry at index/corpus creation time (non-hot path), then uses pre-computed cached strings for efficient O(n) comparisons in the search hot path....
Cmux Swift Concurrency ✅ Passed PR introduces only pure, synchronous functions for search ranking logic in cmux-owned Swift code; no legacy async patterns (DispatchQueue, Combine, fire-and-forget Tasks, completion handlers) are i...
Cmux Swift @Concurrent ✅ Passed All Swift changes are synchronous, pure functions (no async/await, no @concurrent/@MainActor/@Actor annotations). No async work added that requires @concurrent annotations or explicit actor hops fr...
Cmux Swift File And Package Boundaries ✅ Passed All Swift production changes comply with swift-file-package-boundaries.md: CommandPaletteSearchWordText.swift (25 lines, new file with single responsibility); CommandPaletteSearchEngine.swift (280...
Cmux Swiftpm Lockfiles ✅ Passed PR modifies only source code (Rust FFI and Swift search logic) and tests; contains no SwiftPM, Xcode project, .gitignore, workflow, or dependency changes that the rule applies to.
Cmux Swift Logging ✅ Passed No Swift logging violations found in production code. All three modified Swift files contain no print, debugPrint, dump, NSLog, or improperly declared Logger statements.
Cmux User-Facing Error Privacy ✅ Passed PR contains no user-facing error messages, alerts, or recovery copy. Changes are purely algorithmic (search ranking logic) with internal helper functions and tests; no exposed vendor names, credent...
Cmux Full Internationalization ✅ Passed PR contains no user-facing strings or UI text requiring localization; all changes are internal search ranking/scoring logic, test utilities, and implementation helpers with no user-visible text add...
Cmux Swiftui State Layout ✅ Passed PR introduces no SwiftUI state changes. All new CommandPalette search files (CommandPaletteSearchEngine, CommandPaletteFuzzyMatcher, CommandPaletteSearchWordText, etc.) are pure data structures and...
Cmux Architecture Rethink ✅ Passed Swift changes are pure-function correctness fixes with clear ownership (CommandPaletteSearchEngine) and invariant (deterministic ranking). No timing, locking, observers, duplicate wiring, or split...
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR contains only search/ranking logic changes (Swift fuzzy matcher, search engine, Rust FFI) with no NSWindow, NSPanel, NSWindowController, or SwiftUI Window/WindowGroup declarations or modifications.
Cmux Source Artifacts ✅ Passed All 7 changed files are intentional hand-written source and test code in standard product/test locations (Sources, Tests, Native/src directories). No source control artifacts, build output, caches,...
Cmux No Test Or Debug Seam In Production Source ✅ Passed No test/debug seams in production Swift source. All new public members (commandPaletteNormalizedSearchWordText, normalizedTitleSearchWordText) are genuine production ranking functionality, not test...
Description check ✅ Passed The PR description comprehensively covers the summary, testing approach, and verification steps, but lacks explicit mention of a demo video and some checklist items are missing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch task-prioritize-full-search-matches

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 20, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes command palette ranking for emoji-prefixed entries by introducing normalizedTitleSearchWordText — a per-corpus-entry string that strips emoji/symbol-only word segments — and a third scoring tier that exact-matches or prefix-matches query tokens against it, ensuring "🧪 Command Palette" outranks "Command Palette Archive" for the query "command palette".

  • New scoring tier (commandPaletteTitleWordScore): computes an exact/prefix bonus using the new PreparedQuery.normalizedTokenText (tokens joined by single spaces, handling repeated-space queries) compared against the stripped title text; the bonus scales with token count (2000 × max(1, tokenCount)) to stay above multi-token keyword hits.
  • Rust title_literal_score alignment: adds a search_title field (parallel to normalizedTitleSearchWordText) to each Nucleo Candidate; falls through to it after the raw-title atom checks, keeping FFI ranking semantically aligned with the Swift path.
  • Reference scorer and regression tests: CommandPaletteSearchReferenceScoring.swift centralises the combined logic so both the Swift engine and benchmark tests stay in sync; new CommandPaletteEmojiTitleSearchTests cover full-title, prefix-title, and repeated-space queries in both Swift-engine and Nucleo-FFI flavours.

Confidence Score: 5/5

Safe to merge: the new scoring tier is additive, the guard restricts the bonus to entries where stripping emoji segments actually changes the text, and all three regression scenarios are covered by both package and app-target tests.

The logic is self-contained, the reference scorer mirrors the production implementation exactly, and the tests exercise the precise failure modes that prompted the fix. No actor isolation, blocking primitive, or source-control issues are introduced.

No files require special attention.

Important Files Changed

Filename Overview
Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchWordText.swift New 25-line helper deriving search word text from pre-computed PreparedCandidateText: drops segments with no alphanumeric scalars (emoji-only) and joins the rest with single spaces.
Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchEngine.swift Adds commandPaletteTitleWordScore as a third arm of the max() in weightedScore; guard correctly limits the path to entries where stripping emoji segments changes the text.
Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchCorpusEntry.swift Stores normalizedTitleSearchWordText at construction time from the already-computed preparedTitle — no redundant normalization pass.
Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swift Adds normalizedTokenText to PreparedQuery to normalise repeated-space queries; tokens list pre-computed once and reused.
Native/CommandPaletteNucleoFFI/src/lib.rs Adds search_title to Candidate; title_literal_score falls through to search_title after raw-title atom checks, mirroring the Swift path.
Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchReferenceScoring.swift New test-support file centralising commandPaletteWeightedReferenceScore with the full three-arm max().
Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteEmojiTitleSearchTests.swift Regression tests covering emoji-prefixed full-title, prefix-title, and repeated-space query cases against both Swift engine and Nucleo FFI.
cmuxTests/CommandPaletteEmojiTitleSearchTests.swift App-target parallel using the public API, exercising the same three scenarios.
Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchEngineTests.swift Updated to use the shared reference scorer; removed now-redundant local weightedReferenceScore.
cmux.xcodeproj/project.pbxproj Adds CommandPaletteEmojiTitleSearchTests.swift to the cmuxTests target; no new package references.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["weightedScore(preparedQuery, entry)"] --> B{fuzzyScore non-nil?}
    B -- No --> Z[return nil]
    B -- Yes --> C{preparedTitle non-nil AND titleScore non-nil?}
    C -- No --> R1[return fuzzyScore]
    C -- Yes --> D["max(fuzzyScore, titleScore+2000, commandPaletteTitleWordScore??Int.min)"]
    D --> E[commandPaletteTitleWordScore]
    E --> F{query empty OR titleSearchWordText == titleNormalizedText?}
    F -- Yes --> G[return nil]
    F -- No --> H{titleSearchWordText == normalizedTokenText?}
    H -- Yes exact --> I["exactTokenScore + 2000 x tokenCount"]
    H -- No --> J{titleSearchWordText hasPrefix normalizedTokenText?}
    J -- Yes prefix --> K["prefixTokenScore + 2000 x tokenCount"]
    J -- No --> L[return nil]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["weightedScore(preparedQuery, entry)"] --> B{fuzzyScore non-nil?}
    B -- No --> Z[return nil]
    B -- Yes --> C{preparedTitle non-nil AND titleScore non-nil?}
    C -- No --> R1[return fuzzyScore]
    C -- Yes --> D["max(fuzzyScore, titleScore+2000, commandPaletteTitleWordScore??Int.min)"]
    D --> E[commandPaletteTitleWordScore]
    E --> F{query empty OR titleSearchWordText == titleNormalizedText?}
    F -- Yes --> G[return nil]
    F -- No --> H{titleSearchWordText == normalizedTokenText?}
    H -- Yes exact --> I["exactTokenScore + 2000 x tokenCount"]
    H -- No --> J{titleSearchWordText hasPrefix normalizedTokenText?}
    J -- Yes prefix --> K["prefixTokenScore + 2000 x tokenCount"]
    J -- No --> L[return nil]
Loading

Reviews (3): Last reviewed commit: "Prioritize full command palette title ma..." | Re-trigger Greptile

return exactTokenScore + commandPaletteScaledTitleMatchBonus(tokenCount: preparedQuery.tokens.count)
}

guard preparedTitle.normalizedSearchWordText.hasPrefix(preparedQuery.normalizedText) else {

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.

P2 Character-level prefix check can give false prefix matches mid-word

hasPrefix compares characters with no word-boundary awareness. A title whose normalizedSearchWordText is "command palettist" would satisfy hasPrefix("command palette"), earning the same prefix-tier bonus as "command palette archive". In practice this is unlikely to cause a visible mis-ranking (both are reasonable prefix results and they'd share the same score, deferring to rank/title tiebreak), but it is a latent gotcha if titles with words that merely start with a query token start accumulating the prefix bonus in unexpected ways.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +590 to 607
if !candidate.search_title.is_empty()
&& state
.atom_score(&query.exact, &candidate.search_title)
.is_some()
{
return Some(TITLE_EXACT_TOKEN_SCORE * token_count);
}
if state.atom_score(&query.prefix, &candidate.title).is_some() {
return Some(TITLE_PREFIX_TOKEN_SCORE * token_count);
}
if !candidate.search_title.is_empty()
&& state
.atom_score(&query.prefix, &candidate.search_title)
.is_some()
{
return Some(TITLE_PREFIX_TOKEN_SCORE * token_count);
}
None

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.

P2 search_title casing is not normalized before atom_score comparison

title_search_word_text preserves the original casing of the title (e.g. "Command Palette"), so search_title is stored in mixed case. atom_score uses Nucleo's smart-case / case-insensitive matching so a lowercase query like "command palette" still matches "Command Palette" — this works correctly. However, note that if atom_score's case-folding behaviour ever changed or the atom was created with case-sensitive mode, the search_title check would start failing while the raw title check would also fail for emoji-prefixed entries, silently dropping the whole title-literal bonus for those rows. Worth a brief inline comment documenting that search_title relies on Nucleo case folding.

@lawrencecchen
lawrencecchen force-pushed the task-prioritize-full-search-matches branch from 8c02517 to 599a0e1 Compare June 20, 2026 10:08

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 599a0e1. Configure here.

Comment thread Native/CommandPaletteNucleoFFI/src/lib.rs
@lawrencecchen
lawrencecchen force-pushed the task-prioritize-full-search-matches branch from 599a0e1 to f330ee0 Compare June 20, 2026 10:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Native/CommandPaletteNucleoFFI/src/lib.rs`:
- Around line 685-706: The `is_title_word_boundary` function used in
`title_search_word_text` is treating backslash as a word boundary in Rust, but
Swift's `tokenBoundaryChars` does not include backslash, causing ranking
inconsistency. Review the `is_title_word_boundary` function to identify the
boundary character set it uses and either remove the backslash character from
the Rust implementation to match Swift, or add backslash to Swift's
`tokenBoundaryChars` to match Rust, ensuring both implementations split titles
identically.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 32511209-be47-47d2-bb87-97f4b2c1654e

📥 Commits

Reviewing files that changed from the base of the PR and between bbed84b and 599a0e1.

📒 Files selected for processing (7)
  • Native/CommandPaletteNucleoFFI/src/lib.rs
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchEngine.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchWordText.swift
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteEmojiTitleSearchTests.swift
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchEngineTests.swift
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchReferenceScoring.swift

Comment on lines +685 to +706
fn title_search_word_text(title: &str) -> String {
let mut words = Vec::new();
let mut current = String::new();
for character in title.chars() {
if is_title_word_boundary(character) {
append_search_word(&mut words, &mut current);
continue;
}
current.push(character);
}
append_search_word(&mut words, &mut current);
words.join(" ")
}

fn append_search_word(words: &mut Vec<String>, current: &mut String) {
if current.chars().any(char::is_alphanumeric) {
words.push(std::mem::take(current));
} else {
current.clear();
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Align title-word boundary rules between Rust and Swift.

The new search_title path splits on \ in Rust, but Swift’s tokenBoundaryChars does not. That creates ranking drift between Nucleo FFI and Swift fallback for titles containing backslashes, which breaks the parity this PR is aiming for.

Use the same boundary set in both layers (either add \ in Swift or remove it here) so search_title normalization is identical across implementations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Native/CommandPaletteNucleoFFI/src/lib.rs` around lines 685 - 706, The
`is_title_word_boundary` function used in `title_search_word_text` is treating
backslash as a word boundary in Rust, but Swift's `tokenBoundaryChars` does not
include backslash, causing ranking inconsistency. Review the
`is_title_word_boundary` function to identify the boundary character set it uses
and either remove the backslash character from the Rust implementation to match
Swift, or add backslash to Swift's `tokenBoundaryChars` to match Rust, ensuring
both implementations split titles identically.

@lawrencecchen
lawrencecchen force-pushed the task-prioritize-full-search-matches branch 3 times, most recently from 7324e4a to 983c5e3 Compare June 20, 2026 10:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
Native/CommandPaletteNucleoFFI/src/lib.rs (1)

685-706: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Unify title-word boundary rules with Swift to avoid ranking drift.

Line 708 treats \ as a word boundary, but Swift’s CommandPaletteFuzzyMatcher.tokenBoundaryChars (Line 44 in Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swift) does not. That makes search_title normalization diverge between Rust FFI and Swift fallback for backslash-delimited titles.

Suggested minimal fix (align Rust to current Swift boundary set)
 fn is_title_word_boundary(character: char) -> bool {
-    matches!(character, ' ' | '-' | '_' | '/' | '\\' | '.' | ':')
+    matches!(character, ' ' | '-' | '_' | '/' | '.' | ':')
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Native/CommandPaletteNucleoFFI/src/lib.rs` around lines 685 - 706, The Rust
implementation of title_search_word_text uses the is_title_word_boundary
function to determine word boundaries, but it currently treats backslash (\) as
a boundary character, which differs from Swift's
CommandPaletteFuzzyMatcher.tokenBoundaryChars that does not include backslash.
To unify the behavior between Rust FFI and Swift fallback, locate the
is_title_word_boundary function and remove backslash from its set of boundary
characters so the search title normalization matches the Swift implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@Native/CommandPaletteNucleoFFI/src/lib.rs`:
- Around line 685-706: The Rust implementation of title_search_word_text uses
the is_title_word_boundary function to determine word boundaries, but it
currently treats backslash (\) as a boundary character, which differs from
Swift's CommandPaletteFuzzyMatcher.tokenBoundaryChars that does not include
backslash. To unify the behavior between Rust FFI and Swift fallback, locate the
is_title_word_boundary function and remove backslash from its set of boundary
characters so the search title normalization matches the Swift implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: a4559706-0c8b-4271-9d1b-871a272a8072

📥 Commits

Reviewing files that changed from the base of the PR and between 599a0e1 and 31f0658.

📒 Files selected for processing (7)
  • Native/CommandPaletteNucleoFFI/src/lib.rs
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteFuzzyMatcher.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchEngine.swift
  • Packages/macOS/CmuxCommandPalette/Sources/CmuxCommandPalette/Search/CommandPaletteSearchWordText.swift
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteEmojiTitleSearchTests.swift
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchEngineTests.swift
  • Packages/macOS/CmuxCommandPalette/Tests/CmuxCommandPaletteTests/CommandPaletteSearchReferenceScoring.swift

@lawrencecchen
lawrencecchen force-pushed the task-prioritize-full-search-matches branch 4 times, most recently from 6ed6653 to 55f2056 Compare June 20, 2026 10:39
@lawrencecchen
lawrencecchen force-pushed the task-prioritize-full-search-matches branch from 55f2056 to 15fd564 Compare June 20, 2026 10:44
@lawrencecchen
lawrencecchen merged commit 791fe7a into main Jun 20, 2026
31 of 33 checks passed
@lawrencecchen
lawrencecchen deleted the task-prioritize-full-search-matches branch June 20, 2026 11:07

This branch was successfully deployed

1 active deployment
Preview – cmux — 15fd5645 Deployed Jun 20, 2026 by vercel[bot]
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.

1 participant