| … | … | @@ -0,0 +1,375 @@ | |
| 245 | + | } | |
| 246 | + | ||
| 247 | + | function formatQualifierValue(value: string): string { | |
| 248 | + | return /\s/.test(value) ? `"${value}"` : value; | |
🟡 Medium state/threadSearchQuery.ts:248
Selecting a project, provider, or environment label containing a comma filters for its separate comma-delimited values instead of the selected label; labels containing " produce an invalid qualifier. formatQualifierValue only quotes whitespace, and tokenization removes those quotes before validValues splits on commas, so use an encoding the parser preserves or exclude labels containing these delimiters from the menu.
Also found in 1 other location(s)
apps/web/src/components/CommandPaletteThreadFilters.tsx:135
Selecting a project whose title contains a comma produces an incorrect qualifier.
toggleThreadSearchQualifierserializes thisoption.valueas comma-separated values (it only quotes whitespace), so clicking a project namedapi,docswritesproject:api,docs; the parser then treats it as an OR filter forapianddocs, returning unrelated projects rather than the selected one. The same serialization path affects provider/environment labels containing commas.
🤖 Copy this AI Prompt to have your agent fix this:
| 1 | In file @packages/client-runtime/src/state/threadSearchQuery.ts around line 248: |
| 2 | |
| 3 | Selecting a project, provider, or environment label containing a comma filters for its separate comma-delimited values instead of the selected label; labels containing `"` produce an invalid qualifier. `formatQualifierValue` only quotes whitespace, and tokenization removes those quotes before `validValues` splits on commas, so use an encoding the parser preserves or exclude labels containing these delimiters from the menu. |
| 4 | |
| 5 | Also found in 1 other location(s): |
| 6 | - apps/web/src/components/CommandPaletteThreadFilters.tsx:135 -- Selecting a project whose title contains a comma produces an incorrect qualifier. `toggleThreadSearchQualifier` serializes this `option.value` as comma-separated values (it only quotes whitespace), so clicking a project named `api,docs` writes `project:api,docs`; the parser then treats it as an OR filter for `api` and `docs`, returning unrelated projects rather than the selected one. The same serialization path affects provider/environment labels containing commas. |
| … | … | @@ -0,0 +1,375 @@ | |
| 209 | + | hasFilters = true; | |
| 210 | + | } | |
| 211 | + | continue; | |
| 212 | + | } | |
🟡 Medium state/threadSearchQuery.ts:206
-is:archived is discarded, so is:archived -is:archived still parses as an archived-only query and matches archived threads instead of none. The special case continues for both polarities, while ThreadSearchFilters.archived cannot represent negation; let the negative token remain as free text or add an explicit negated archive filter.
| 1 | - if (candidate.toLowerCase() === "is:archived") { |
| 2 | - if (!negated) { |
| 3 | - archived = true; |
| 4 | - hasFilters = true; |
| 5 | - } |
| 6 | + if (candidate.toLowerCase() === "is:archived" && !negated) { |
| 7 | + archived = true; |
| 8 | + hasFilters = true; |
| 9 | continue; |
| 10 | } |
🤖 Copy this AI Prompt to have your agent fix this:
| 1 | In file @packages/client-runtime/src/state/threadSearchQuery.ts around lines 206-212: |
| 2 | |
| 3 | `-is:archived` is discarded, so `is:archived -is:archived` still parses as an archived-only query and matches archived threads instead of none. The special case continues for both polarities, while `ThreadSearchFilters.archived` cannot represent negation; let the negative token remain as free text or add an explicit negated archive filter. |
| … | … | @@ -338,6 +379,10 @@ export function CommandPalette(props: { | |
| 338 | 379 | thread.branch ?? "", | |
| 339 | 380 | ...threadPullRequestSearchTerms(thread), | |
| 340 | 381 | ], | |
| 382 | + | matchesSearch: () => | |
🟡 Medium keyboard/CommandPalette.tsx:382
A qualifier-only query such as is:archived leaves unrelated actions ahead of matching threads, so pressing Enter selects New thread in… instead of opening the first matching archived thread. matchesSearch narrows thread rows, but filterCommandPaletteItems still sees the original query and retains actions; suppress unrelated actions or prioritize matching threads for qualifier-only searches.
🤖 Copy this AI Prompt to have your agent fix this:
| 1 | In file @apps/mobile/src/features/keyboard/CommandPalette.tsx around line 382: |
| 2 | |
| 3 | A qualifier-only query such as `is:archived` leaves unrelated actions ahead of matching threads, so pressing Enter selects `New thread in…` instead of opening the first matching archived thread. `matchesSearch` narrows thread rows, but `filterCommandPaletteItems` still sees the original query and retains actions; suppress unrelated actions or prioritize matching threads for qualifier-only searches. |
| … | … | @@ -245,7 +254,25 @@ export function HomeScreen(props: HomeScreenProps) { | |
| 246 | 255 | [props.environments, props.selectedEnvironmentId], | |
| 247 | 256 | ); | |
| 248 | - | const threadSearch = useThreadSearch(searchEnvironmentIds, props.searchQuery); | |
| 257 | + | const archivedSnapshots = useArchivedThreadSnapshots( | |
🟠 High home/HomeScreen.tsx:257
An account with no active threads or pending tasks shows the full-page “No threads yet” state for is:archived, so archived search results are never rendered. The hasAnyThreads guard only checks active props.threads and pending tasks; include archived snapshot results when the archived filter is active.
🤖 Copy this AI Prompt to have your agent fix this:
| 1 | In file @apps/mobile/src/features/home/HomeScreen.tsx around line 257: |
| 2 | |
| 3 | An account with no active threads or pending tasks shows the full-page “No threads yet” state for `is:archived`, so archived search results are never rendered. The `hasAnyThreads` guard only checks active `props.threads` and pending tasks; include archived snapshot results when the archived filter is active. |
| … | … | @@ -2864,21 +2882,67 @@ export default function Sidebar() { | |
| 2875 | - | ...settledThreads, | |
| 2896 | + | () => | |
| 2897 | + | parsedThreadSearch.filters.archived | |
| 2898 | + | ? archivedSnapshots.snapshots | |
🟠 High components/Sidebar.tsx:2898
Dropping files onto an is:archived search result queues them for an archived thread, then attempts to navigate to its live thread route; because that route does not exist, the pending drop is cleared and the files are lost. Archived results use the normal onFileDropThreads handler, so disable file drops for them or route drops through an archived-thread-capable flow.
🤖 Copy this AI Prompt to have your agent fix this:
| 1 | In file @apps/web/src/components/Sidebar.tsx around line 2898: |
| 2 | |
| 3 | Dropping files onto an `is:archived` search result queues them for an archived thread, then attempts to navigate to its live thread route; because that route does not exist, the pending drop is cleared and the files are lost. Archived results use the normal `onFileDropThreads` handler, so disable file drops for them or route drops through an archived-thread-capable flow. |
| … | … | @@ -601,7 +650,7 @@ export function HomeScreen(props: HomeScreenProps) { | |
| 602 | 651 | // while their environment is offline. Same environment scope and search | |
| 603 | 652 | // filter as the list itself. | |
| 604 | - | const v2SearchQuery = props.searchQuery.trim().toLocaleLowerCase(); | |
| 653 | + | const v2SearchQuery = parsedSearch.text.trim().toLocaleLowerCase(); | |
🟡 Medium home/HomeScreen.tsx:653
Qualifier-only searches still show pending-task rows that cannot match the requested thread qualifier; for example, is:archived leaves v2SearchQuery empty, so every in-scope pending task passes the filter and appears in the archive-only results. Exclude pending tasks for qualifiers they cannot satisfy, or apply the relevant parsed filters before adding them to the list.
Also found in 1 other location(s)
apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx:479
Recognized qualifiers are stripped into
parsedSearch.text, but pending tasks are filtered only by that free text. Consequently a qualifier-only query such asis:archived(orstatus:failed,project:docs, etc.) still renders every matching-title pending task, even though pending tasks cannot be archived or match the requested thread qualifier. Apply the parsed filters to pending tasks where meaningful, or exclude pending tasks whenever qualifiers are active.
🤖 Copy this AI Prompt to have your agent fix this:
| 1 | In file @apps/mobile/src/features/home/HomeScreen.tsx around line 653: |
| 2 | |
| 3 | Qualifier-only searches still show pending-task rows that cannot match the requested thread qualifier; for example, `is:archived` leaves `v2SearchQuery` empty, so every in-scope pending task passes the filter and appears in the archive-only results. Exclude pending tasks for qualifiers they cannot satisfy, or apply the relevant parsed filters before adding them to the list. |
| 4 | |
| 5 | Also found in 1 other location(s): |
| 6 | - apps/mobile/src/features/threads/ThreadNavigationSidebar.tsx:479 -- Recognized qualifiers are stripped into `parsedSearch.text`, but pending tasks are filtered only by that free text. Consequently a qualifier-only query such as `is:archived` (or `status:failed`, `project:docs`, etc.) still renders every matching-title pending task, even though pending tasks cannot be archived or match the requested thread qualifier. Apply the parsed filters to pending tasks where meaningful, or exclude pending tasks whenever qualifiers are active. |