Skip to content

fix(search): refuse unknown fields and boosts, one name per concept, faster coverage - #2871

Merged
leemour merged 1 commit into
mainfrom
fix/search-gaps
Nov 12, 2026
Merged

leemour merged 1 commit into
mainfrom
fix/search-gaps

Conversation

@leemour

@leemour leemour commented Nov 11, 2026

Copy link
Copy Markdown
Member

Task

Fix the search gaps of the 2026-11-11 audit that the owner approved (NEED-2560 answer A, TASK-986), in one PR. The
shape of search results and pagination is unchanged.

Why

Agents and people wrote queries that found nothing and said nothing (status:open, invoice^2, author: in messages),
used two names for one concept, or hit a refusal that named no alternative. Every message search also spent about
0.45 s at 1M messages counting every chat's messages for its coverage.

What

Gap Example Before After
BUG-740 unknown field status:open searched as the words, 0 hits, no error query.unknown-field: tasks list status:open, or quote it
BUG-740 notes field in messages author:x, site:x 0 hits, no error query.unsupported-field: "a notes field — search notes reads it"
BUG-741 boost invoice^2 searched the text "invoice^2", 0 hits query.unsupported-operator: drop it (invoice) or quote it
UX-221 aliases sender:olga, title:Альфа sender: unknown; title: matched nothing in messages sender: is from:; title: is the chat title (messages) and the subject (mail); one mapping table in the guide
UX-224 presence _exists_:from, subject:* refused / unsupported keeps messages that have a value; other fields refuse with has:file, has:link…
UX-223 tasks tasks list request, title:request query.bare-word / title prefix only finds "Review the request"
UX-223 contacts contacts list phone:+34, email:example.com +34 misparsed; no email/phone matched (phone by digits)
UX-223 deals search all title:Поставка words anywhere in the deal the deal's or lead's title only
UX-222 reasons chat:Альфа* fitting nothing; 2-letter chat search bare not_found / validation query.no-match with chat:*Альфа*; query.short-text with a hint
PERF-99 word end *ени at 1M refused (candidate rows), no term named 50 hits in 647 ms; a page it cannot fill names the term and suggests *part*
PERF-100 coverage договор* at 1M 478 ms 31 ms (coverage read 445 ms → 0.2 ms)
DEBT-326 after: reason legacy_date_field (not registrable) query.legacy-date-field, registered; the reasons test now also reads searchError(...)
DEBT-327 bin/verify-query-reference on JDK 25 failed on Java object ids passes on JDK 21 and 25

Not done, and why:

  • Tasks in search all: memo's MCP gates each search all lane by permission and has no tasks gate, so a tasks
    lane would show task titles where tasks.list is denied. It needs memo's gate in the same bump.
  • Meeting description, and title: in meetings search: needs a new hit scope or a folded description column
    (a migration). Meeting titles already match in search all.

Breaking items are under "Changed — may break callers" in the changelog fragment.

Measurement: cli-testing, performance/search/coverage-step
(WireCatLabs/cli-testing#356).

Testing

  • Each new or changed test fails on main's sources (25 tests in 14 files) and passes here.
  • typecheck, lint, docs:check and the full suite pass locally; verify-query-reference passes on JDK 21 and 25.
  • Every behavior in the table was run against a seeded synthetic store, before (main's dist) and after.

🤖 Generated with Claude Code

…faster coverage

The search gaps the 2026-11-11 audit found (NEED-2560 A, TASK-986):

- BUG-740: an unknown field (`status:open`) or a notes field in message search
  (`author:`, `site:`) is refused with what to write instead, not searched as
  words that find nothing.
- BUG-741: a boost (`invoice^2`) is refused with the query to retry.
- UX-221: `sender:` is `from:`; `title:` is the chat title in messages and the
  subject in mail; one mapping table in the query guide.
- UX-222: name not_found, the three-character minimums and title patterns say
  what to write and carry reason codes (query.no-match, query.short-text).
- UX-223: task titles by word and bare word, contacts email:/phone:, deals by
  title: in search all.
- UX-224: field:* and _exists_:field mean presence in message and mail search.
- PERF-99: word-end patterns are checked up to the page; the refusal names the
  term and suggests *part*.
- PERF-100: coverage reads chats.message_count and each chat's newest message
  off its time index (478 ms -> 31 ms for a search at 1M messages).
- DEBT-326/327: query.legacy-date-field registered (renamed from
  legacy_date_field); verify-query-reference normalizes Java object ids.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@leemour
leemour merged commit 7b2754a into main Nov 12, 2026
43 checks passed
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