Thread search can't find phrases inside quotes and quote comments, and shows raw `t3-citation` links in results#22304

opened21d agobyEEtanHey

What happened

I quoted an assistant message and added the comment "what are you talking about". Later I searched for that comment and got No threads found. The sidebar search and the command palette gave the same result.

  • Searching the comment phrase what are you talking about: 0 threads.
  • Searching a 3-word phrase from the quoted text (ships safely through): only the original assistant message is found, not my message that quotes it.
  • Searching plain text from the same message (quiet silver lantern): found.
  • A single word from the comment (e.g. talking) is found.

When the quoting message does show up in results, its snippet is the raw link, for example You: [Assistant quote](t3-citation://v1/f665… or You: …0dd8de?text=A+lighthouse+guides+ships+safely+through+the+darkness.%0A%0A&start=0&…, instead of the quote text or comment.

Diagnosis

Both symptoms have one cause: search runs over the stored message text, and a quote is stored there as a serialized link, not readable text.

  • packages/shared/src/assistantCitations.ts:36-49 (formatAssistantCitationHref) puts the quote text and comment into URLSearchParams, so spaces become + and punctuation is percent-encoded (comment=what+are+you+talking+about). serializeAssistantCitation (:104-106) wraps that as [Assistant quote](t3-citation://v1/…) in the message text.
  • apps/server/src/orchestration-v2/ThreadSearch.ts:84 and :98 match with json_extract(messages.payload_json, '$.text') LIKE '%query%' on that raw text. what are you talking about is not a substring of what+are+you+talking+about, so any phrase with a space (or an apostrophe, comma, etc.) inside a quote or comment can never match. Single words still match because they appear unencoded between the + signs.
  • The same raw text becomes the result snippet: buildSearchSnippet(row.matchText, …) at ThreadSearch.ts:46-60 and :157, rendered as-is by apps/web/src/components/ThreadSearchMatch.tsx:50-66. Sidebar (Sidebar.tsx:2683) and palette (CommandPaletteResults.tsx:170,220) both use it, so both show the markup.
  • Also, results prefer a user message over an assistant one in the same thread (ThreadSearch.ts:107-115). If a thread quotes its own assistant message, the user message can never win on a multi-word phrase, so the result falls back to the agent message.

The readable form already exists: assistantCitationsToPlainText (assistantCitations.ts:124-132) turns each link into text + Comment: …. One possible fix: match and build snippets from that plain-text form, for example via a derived search-text column written when the message is projected, so the SQL LIKE stays on the reader worker. A smaller interim step: run the snippet through assistantCitationsToPlainText so results stop showing link markup.

Checked at 2fcefc9abf. No commits between that and current upstream main (70a869d262) touch ThreadSearch.ts, assistantCitations.ts or ThreadSearchMatch.tsx. I did not re-run the repro on 70a869d262.

Steps to reproduce

  1. In thread A, get an assistant reply that contains a sentence such as "A lighthouse guides ships safely through the darkness."
  2. Select that sentence, click Cite, add the comment what are you talking about, and save.
  3. Paste the quote into a new thread B, add the text quiet silver lantern, and send.
  4. Search for what are you talking about in the sidebar, then in the command palette (Cmd/Ctrl+K). Result: 0 threads.
  5. Search for ships safely through. Result: only thread A (Agent snippet). Thread B is missing.
  6. Search for quiet silver lantern. Result: thread B, with a snippet full of ?text=A+lighthouse+…&comment=what+are+you+talking+about.
  7. Search for Assistant quote. The snippet starts with You: [Assistant quote](t3-citation://v1/….

Expected: steps 4 and 5 find thread B, and snippets show the quote or comment as readable text.

Version

T3 Code dev build from main at 2fcefc9abf. First noticed on desktop Nightly 0.1.1-nightly.20261020.3386.

Environment

macOS on Apple M1 Pro, isolated local web dev build (server + web dev server), viewport 1280x900. Codex provider. Provider version doesn't matter: search reads the projection DB.

Evidence

shell
1# Stored text of the user message in thread B (citation part):
2[Assistant quote](t3-citation://v1/<env-id>/thread%3Aproject%3A<project-id>%3A<thread-id>/message%3Aprovider%3Acodex%3Anative-item%3Amsg_…?text=A+lighthouse+guides+ships+safely+through+the+darkness.%0A%0A&start=0&end=55&prefix=&suffix=%28%7B+beacon01%3A+illuminate%28%22norther&comment=what+are+you+talking+about) quiet silver lantern. Reply only OK; do not use tools.
3
4# Search results (sidebar and command palette gave the same):
5"what are you talking about" -> 0 threads
6"ships safely through" -> 1 thread: thread A, "Agent: A lighthouse guides ships safely through the darkness. …" (thread B missing)
7"quiet silver lantern" -> 1 thread: thread B, "You: …0dd8de?text=A+lighthouse+guides+ships+safely+through+the+darkness.%0A%0A&start=0&…"
8"Assistant quote" -> thread B and thread A, both "You: [Assistant quote](t3-citation://v1/…"

Screenshots:

The sent message in thread B: the quote chip shows the comment "what are you talking about".

C2-sent-message

Sidebar search for the comment: "No threads found", while the same text is visible in the chip on the right.

C2-sidebar-comment

The command palette gives the same empty result.

C2-palette-comment

ships safely through finds only thread A (Agent snippet); thread B is missing.

C2-sidebar-quoted

quiet silver lantern finds thread B, with an encoded-link snippet.

C2-sidebar-plain

Assistant quote results show raw [Assistant quote](t3-citation://v1/… snippets.

C2-raw-citation-snippet

Same family, different surfaces: #22076 (collapsed composer shows raw t3-citation links), #16327 (raw links reach providers), #12331 / #18987 (closed: raw links in queued messages). #22109 is a different quote bug (comment popover position). None of these covers thread search: matching or snippets. #16858 (open PR, search qualifiers) changes query parsing but still sends free text to the same LIKE, so it doesn't fix this.

Fix applied or workaround

None applied. Workaround: search for a single distinctive word from the quote or comment instead of a phrase.

Filed by

t3 triage, run by Claude Code (Claude Opus 5.5)

— EtanHey's t3codeClaude (worker) · claude-code/claude-opus-5-5