Skip to content

feat(#6645): use AND semantics for docs site multi-word search - #6799

Open
fullsend-ai-coder[bot] wants to merge 3 commits into
mainfrom
agent/6645-docs-search-and-semantics
Open

feat(#6645): use AND semantics for docs site multi-word search#6799
fullsend-ai-coder[bot] wants to merge 3 commits into
mainfrom
agent/6645-docs-search-and-semantics

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Summary

Switches the vendored docs site search (VPLocalSearchBox.vue) from OR to AND semantics for multi-word queries, so searching for eval scenario returns only pages containing both terms. Adds exact-phrase support: wrapping a query in double quotes ("eval scenario") post-filters results to pages where the phrase appears adjacent.

Changes

  • docs/.vitepress/theme/searchQuery.ts — new utility module with parseSearchQuery() (extracts double-quoted phrases) and textContainsPhrases() (case-insensitive substring check)
  • docs/.vitepress/theme/components/VPLocalSearchBox.vue — passes combineWith: 'AND' to index.search(); parses query for quoted phrases; adds loadPageText() helper that renders a page module to plain text; post-filters results for exact phrase matches when quotes are present
  • docs/.vitepress/theme/searchQuery.test.ts — 17 unit tests covering query parsing edge cases and phrase matching

Testing

  • vitest run passes (44 tests, 3 test files)
  • prettier --check passes on all changed files
  • stylelint passes on the Vue component
  • Single-word queries are unaffected (AND/OR is equivalent for one term)
  • Scope filtering (matchesActiveScopes) is preserved — the filter function is merged into the same search options object

Closes #6645

Post-script verification

  • Branch is not main/master (agent/6645-docs-search-and-semantics)
  • Secret scan passed (gitleaks — 92c1d6498c16ee9fa490150a6405c1bb974aff4a..HEAD)
  • PR body secret scan passed (gitleaks — no-git)

Multi-word queries in the vendored VPLocalSearchBox now require all
terms to appear on the same page (combineWith: 'AND') instead of
matching any term independently (the MiniSearch default of OR).

Quoted phrases like "eval scenario" trigger exact-phrase
post-filtering: after the AND search, page modules are rendered
and their plain text is checked for the adjacent phrase. Results
whose page text cannot be loaded are kept (graceful degradation).

Changes:
- searchQuery.ts: parseSearchQuery() extracts double-quoted
  phrases; textContainsPhrases() checks case-insensitive
  substring matches.
- VPLocalSearchBox.vue: search call uses combineWith 'AND',
  parses query for phrases, post-filters via loadPageText().
- searchQuery.test.ts: 17 unit tests covering query parsing
  and phrase matching.

Closes #6645
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

Site preview

Preview: https://58f6cc64-site.fullsend-ai.workers.dev

Commit: 6a93355289b7578b5cd311b94745b0cccf4137f1

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 31, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:13 PM UTC · Completed 2:27 PM UTC

Commit: f65eed5 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $3.72

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review fullsend-ai-review Bot added the risk/low PR risk: low label Aug 31, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 31, 2026

Copy link
Copy Markdown

Risk Assessment: low (1/5)

Details

Small, well-scoped docs-site search enhancement by a known bot author with good test coverage, stable file history, and full alignment with issue #6645's acceptance criteria. Tier 1 signals slightly elevated (4 files, 271 lines, medium blast radius) but offset by zero protected paths, zero security-sensitive files, no dependency changes, and strong Tier 2/3 signals. Composite rounds to 1, consistent with prior assessment.

Previous run

Risk Assessment: low (1/5)

Details

Small, well-scoped docs-site search enhancement by a known bot author with good test coverage, stable file history, and full alignment with issue #6645's acceptance criteria. Re-review: all Tier 1 signals unchanged from prior assessment; score remains 1.

Previous run (2)

Risk Assessment: low (1/5)

Details

Small, well-scoped docs-site search enhancement by a known bot author with good test coverage, stable file history, and full alignment with a recent issue's acceptance criteria.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 31, 2026

Copy link
Copy Markdown

Review

Findings

Low

  • [edge-case] docs/.vitepress/theme/searchQuery.ts:49filterByPhrases silently keeps results that have no content (empty title, titles, and text) via the if (!content.trim()) return true guard. If MiniSearch fails to populate text in storeFields for certain documents — e.g., due to an index format change in a VitePress upgrade — those results would bypass phrase filtering entirely without any visible indication. The behavior is documented as graceful degradation, tested, and is a reasonable tradeoff, but the failure mode is silent.
Previous run

Looks good to me

Previous run (2)

Review

Findings

Low

  • [edge-case] docs/.vitepress/theme/searchQuery.ts:25 — When two quoted phrases appear without whitespace between them (e.g., "foo bar""baz qux"), the regex replacement concatenates the trailing word of the first phrase with the leading word of the second in the query string (producing foo barbaz qux). This feeds a non-existent fused token to MiniSearch AND search, causing it to return zero results even though both phrases exist on the page.
    Remediation: Pad the replacement with a space: return " " + trimmed (the outer .trim() already strips leading/trailing whitespace), or normalize consecutive spaces in the final query.

  • [type-annotation-style] docs/.vitepress/theme/components/VPLocalSearchBox.vue:183 — The variable searchOpts is typed as Record<string, unknown>. A narrower type like { combineWith: string; filter?: (r: SearchResult) => boolean } would be more precise and catch typos at compile time.
    Remediation: Consider typing searchOpts more precisely: const searchOpts: { combineWith: string; filter?: (r: SearchResult) => boolean } = { combineWith: "AND" };

  • [missing-documentation] docs/doc-site.md:28docs/doc-site.md describes the search modal's scope-based filtering behavior but does not mention the new AND semantics for multi-word queries or the exact-phrase matching feature for quoted strings. These are user-visible behavioral changes to the same search component documented in this file.
    Remediation: Add a bullet point describing the search query behavior: multi-word queries use AND semantics (all terms must appear on a page), and double-quoted substrings are matched as exact phrases.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-coder

fullsend-ai-coder Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 2:29 PM UTC · Completed 2:35 PM UTC

Commit: f65eed5 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $1.26

- Fix adjacent quoted phrases fusing tokens by padding replacements
  with spaces and normalizing whitespace in the final query string
  (e.g. "foo bar""baz qux" now produces "foo bar baz qux")
- Narrow searchOpts type from Record<string, unknown> to an explicit
  { combineWith: string; filter?: ... } for compile-time safety
- Document AND semantics and exact-phrase matching in docs/doc-site.md
- Add test for adjacent quoted phrases edge case

Addresses review feedback on #6799
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 1 (bot-triggered)

Addressed all 3 review findings: fixed adjacent-quotes edge case in parseSearchQuery with space-padded replacement and whitespace normalization, narrowed searchOpts type annotation for compile-time safety, and documented AND/phrase search behavior in doc-site.md.

Fixed (3):

  1. adjacent quoted phrases fuse tokens in parseSearchQuery (docs/.vitepress/theme/searchQuery.ts): Padded regex replacement with spaces and normalized consecutive whitespace in the final query string so adjacent quoted phrases like '"foo bar""baz qux"' produce 'foo bar baz qux' instead of 'foo barbaz qux'. Added a test covering this edge case.
  2. searchOpts typed as Record<string, unknown> (docs/.vitepress/theme/components/VPLocalSearchBox.vue): Narrowed type from Record<string, unknown> to { combineWith: string; filter?: (r: SearchResult) => boolean } for compile-time safety and typo detection.
  3. missing documentation for AND semantics and exact-phrase matching (docs/doc-site.md): Added a bullet point in the 'How it works' section documenting that multi-word queries use AND semantics and double-quoted substrings enable exact-phrase matching.

Tests: passed

Next steps:

  • /fs-review — request a re-review of the changes
  • /fs-fix <your instruction> — run another fix pass with specific guidance
  • Push commits directly — review re-runs automatically on push
    Updated by fullsend fix agent

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 31, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:37 PM UTC · Completed 2:53 PM UTC

Commit: 1034193 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $4.66

@fullsend-ai-review
fullsend-ai-review Bot dismissed their stale review August 31, 2026 14:53

Superseded by updated review

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Aug 31, 2026
loadPageText() silently failed for every page because VitePress
components need runtime context not provided in the detached render.
The catch returned "" and graceful degradation kept all results,
making the phrase filter a no-op.

Replace with filterByPhrases() that checks against the text already
stored in the MiniSearch index (added "text" to storeFields). This
is synchronous, testable, and doesn't depend on page rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Marta Anon <manon@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 31, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 4:47 PM UTC · Completed 5:01 PM UTC

Commit: 6a93355 · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $3.51

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-merge All reviewers approved — ready to merge ready-for-review Agent PR ready for human review risk/low PR risk: low

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Docs search: multi-word queries match each term independently, making overloaded terms unsearchable

1 participant