@@ -33,6 +33,27 @@ const rows: TimelineRow[] = [
3333 ] ,
3434 } ,
3535 } ,
36+ {
37+ kind : "message" ,
38+ id : "assistant-markdown-row" ,
39+ createdAt : "2026-03-28T12:00:02.000Z" ,
40+ durationStart : "2026-03-28T12:00:02.000Z" ,
41+ showCompletionDivider : false ,
42+ message : {
43+ id : MessageId . makeUnsafe ( "message-1a" ) ,
44+ role : "assistant" ,
45+ text : [
46+ "See [thread search docs](https://example.com/thread-search) for **alpha marker** details." ,
47+ "" ,
48+ "```ts" ,
49+ "const planSeed = 'seeded';" ,
50+ "```" ,
51+ ] . join ( "\n" ) ,
52+ createdAt : "2026-03-28T12:00:02.000Z" ,
53+ streaming : false ,
54+ attachments : [ ] ,
55+ } ,
56+ } ,
3657 {
3758 kind : "message" ,
3859 id : "user-message-row" ,
@@ -110,13 +131,36 @@ const rows: TimelineRow[] = [
110131 proposedPlan : {
111132 id : "plan-1" as never ,
112133 turnId : null ,
113- planMarkdown : "1. Add thread search\n2. Jump to the matching row" ,
134+ planMarkdown : [
135+ "# Seeded Thread Search Plan" ,
136+ "" ,
137+ "## Summary" ,
138+ "" ,
139+ "1. Add **thread search**" ,
140+ "2. Jump to the matching row" ,
141+ "3. Review [plan docs](https://example.com/plan-docs)" ,
142+ ] . join ( "\n" ) ,
114143 implementedAt : null ,
115144 implementationThreadId : null ,
116145 createdAt : "2026-03-28T12:00:20.000Z" ,
117146 updatedAt : "2026-03-28T12:00:20.000Z" ,
118147 } ,
119148 } ,
149+ {
150+ kind : "message" ,
151+ id : "assistant-empty-row" ,
152+ createdAt : "2026-03-28T12:00:25.000Z" ,
153+ durationStart : "2026-03-28T12:00:25.000Z" ,
154+ showCompletionDivider : false ,
155+ message : {
156+ id : MessageId . makeUnsafe ( "message-empty" ) ,
157+ role : "assistant" ,
158+ text : "" ,
159+ createdAt : "2026-03-28T12:00:25.000Z" ,
160+ streaming : false ,
161+ attachments : [ ] ,
162+ } ,
163+ } ,
120164 {
121165 kind : "working" ,
122166 id : "working-row" ,
@@ -133,8 +177,15 @@ describe("findThreadSearchResults", () => {
133177 normalizedTexts : [ "needle in the response. another needle is here." ] ,
134178 } ,
135179 {
136- rowId : "user-message -row" ,
180+ rowId : "assistant-markdown -row" ,
137181 rowIndex : 1 ,
182+ normalizedTexts : [
183+ "see thread search docs for alpha marker details.\n\nconst planseed = 'seeded';" ,
184+ ] ,
185+ } ,
186+ {
187+ rowId : "user-message-row" ,
188+ rowIndex : 2 ,
138189 normalizedTexts : [
139190 "visible composer text @terminal-1:1-5" ,
140191 "terminal 1 lines 1-5" ,
@@ -143,12 +194,12 @@ describe("findThreadSearchResults", () => {
143194 } ,
144195 {
145196 rowId : "work-row" ,
146- rowIndex : 2 ,
197+ rowIndex : 3 ,
147198 normalizedTexts : [ "edit readme" , "bun run lint" , "readme.md" ] ,
148199 } ,
149200 {
150201 rowId : "work-row-visible-files" ,
151- rowIndex : 3 ,
202+ rowIndex : 4 ,
152203 normalizedTexts : [
153204 "apply patch" ,
154205 "git status" ,
@@ -160,12 +211,20 @@ describe("findThreadSearchResults", () => {
160211 } ,
161212 {
162213 rowId : "plan-row" ,
163- rowIndex : 4 ,
164- normalizedTexts : [ "1. add thread search\n2. jump to the matching row" ] ,
214+ rowIndex : 5 ,
215+ normalizedTexts : [
216+ "seeded thread search plan" ,
217+ "add thread search\njump to the matching row\nreview plan docs" ,
218+ ] ,
219+ } ,
220+ {
221+ rowId : "assistant-empty-row" ,
222+ rowIndex : 6 ,
223+ normalizedTexts : [ "(empty response)" ] ,
165224 } ,
166225 {
167226 rowId : "working-row" ,
168- rowIndex : 5 ,
227+ rowIndex : 7 ,
169228 normalizedTexts : [ ] ,
170229 } ,
171230 ] ) ;
@@ -185,7 +244,7 @@ describe("findThreadSearchResults", () => {
185244 expect ( findThreadSearchResults ( rows , "readme" ) ) . toEqual ( [
186245 {
187246 rowId : "work-row" ,
188- rowIndex : 2 ,
247+ rowIndex : 3 ,
189248 matchCount : 2 ,
190249 } ,
191250 ] ) ;
@@ -195,17 +254,17 @@ describe("findThreadSearchResults", () => {
195254 expect ( findThreadSearchResults ( rows , "edit readme" ) ) . toEqual ( [
196255 {
197256 rowId : "work-row" ,
198- rowIndex : 2 ,
257+ rowIndex : 3 ,
199258 matchCount : 1 ,
200259 } ,
201260 ] ) ;
202261 } ) ;
203262
204- it ( "matches proposed plans and ignores the working indicator" , ( ) => {
205- expect ( findThreadSearchResults ( rows , "thread search " ) ) . toEqual ( [
263+ it ( "matches displayed proposed-plan body content and ignores the working indicator" , ( ) => {
264+ expect ( findThreadSearchResults ( rows , "jump to the matching row " ) ) . toEqual ( [
206265 {
207266 rowId : "plan-row" ,
208- rowIndex : 4 ,
267+ rowIndex : 5 ,
209268 matchCount : 1 ,
210269 } ,
211270 ] ) ;
@@ -218,21 +277,21 @@ describe("findThreadSearchResults", () => {
218277 expect ( findThreadSearchResults ( rows , "visible composer text" ) ) . toEqual ( [
219278 {
220279 rowId : "user-message-row" ,
221- rowIndex : 1 ,
280+ rowIndex : 2 ,
222281 matchCount : 1 ,
223282 } ,
224283 ] ) ;
225284 expect ( findThreadSearchResults ( rows , "terminal 1 lines 1-5" ) ) . toEqual ( [
226285 {
227286 rowId : "user-message-row" ,
228- rowIndex : 1 ,
287+ rowIndex : 2 ,
229288 matchCount : 1 ,
230289 } ,
231290 ] ) ;
232291 expect ( findThreadSearchResults ( rows , "visible-upload-name" ) ) . toEqual ( [
233292 {
234293 rowId : "user-message-row" ,
235- rowIndex : 1 ,
294+ rowIndex : 2 ,
236295 matchCount : 1 ,
237296 } ,
238297 ] ) ;
@@ -242,21 +301,68 @@ describe("findThreadSearchResults", () => {
242301 expect ( findThreadSearchResults ( rows , "apply patch" ) ) . toEqual ( [
243302 {
244303 rowId : "work-row-visible-files" ,
245- rowIndex : 3 ,
304+ rowIndex : 4 ,
246305 matchCount : 1 ,
247306 } ,
248307 ] ) ;
249308 expect ( findThreadSearchResults ( rows , "completed" ) ) . toEqual ( [ ] ) ;
250309 expect ( findThreadSearchResults ( rows , "src/d.ts" ) ) . toEqual ( [
251310 {
252311 rowId : "work-row-visible-files" ,
253- rowIndex : 3 ,
312+ rowIndex : 4 ,
254313 matchCount : 1 ,
255314 } ,
256315 ] ) ;
257316 expect ( findThreadSearchResults ( rows , "src/e.ts" ) ) . toEqual ( [ ] ) ;
258317 } ) ;
259318
319+ it ( "indexes assistant markdown by rendered text instead of raw markdown syntax" , ( ) => {
320+ expect ( findThreadSearchResults ( rows , "thread search docs" ) ) . toEqual ( [
321+ {
322+ rowId : "assistant-markdown-row" ,
323+ rowIndex : 1 ,
324+ matchCount : 1 ,
325+ } ,
326+ ] ) ;
327+ expect ( findThreadSearchResults ( rows , "alpha marker" ) ) . toEqual ( [
328+ {
329+ rowId : "assistant-markdown-row" ,
330+ rowIndex : 1 ,
331+ matchCount : 1 ,
332+ } ,
333+ ] ) ;
334+ expect ( findThreadSearchResults ( rows , "https://example.com/thread-search" ) ) . toEqual ( [ ] ) ;
335+ } ) ;
336+
337+ it ( "indexes proposed plans by displayed title and body instead of raw markdown" , ( ) => {
338+ expect ( findThreadSearchResults ( rows , "seeded thread search plan" ) ) . toEqual ( [
339+ {
340+ rowId : "plan-row" ,
341+ rowIndex : 5 ,
342+ matchCount : 1 ,
343+ } ,
344+ ] ) ;
345+ expect ( findThreadSearchResults ( rows , "plan docs" ) ) . toEqual ( [
346+ {
347+ rowId : "plan-row" ,
348+ rowIndex : 5 ,
349+ matchCount : 1 ,
350+ } ,
351+ ] ) ;
352+ expect ( findThreadSearchResults ( rows , "summary" ) ) . toEqual ( [ ] ) ;
353+ expect ( findThreadSearchResults ( rows , "https://example.com/plan-docs" ) ) . toEqual ( [ ] ) ;
354+ } ) ;
355+
356+ it ( "indexes the rendered empty assistant placeholder text" , ( ) => {
357+ expect ( findThreadSearchResults ( rows , "(empty response)" ) ) . toEqual ( [
358+ {
359+ rowId : "assistant-empty-row" ,
360+ rowIndex : 6 ,
361+ matchCount : 1 ,
362+ } ,
363+ ] ) ;
364+ } ) ;
365+
260366 it ( "returns no results for empty queries" , ( ) => {
261367 expect ( findThreadSearchResults ( rows , " " ) ) . toEqual ( [ ] ) ;
262368 } ) ;
@@ -265,7 +371,7 @@ describe("findThreadSearchResults", () => {
265371 expect ( findThreadSearchResults ( rows , "row" ) ) . toEqual ( [
266372 {
267373 rowId : "plan-row" ,
268- rowIndex : 4 ,
374+ rowIndex : 5 ,
269375 matchCount : 1 ,
270376 } ,
271377 ] ) ;
@@ -299,7 +405,10 @@ describe("findThreadSearchResults", () => {
299405 const previousState = findThreadSearchLookupState ( index , "thread search" ) ;
300406 const nextState = findThreadSearchLookupState ( index , "e" , previousState ) ;
301407
302- expect ( previousState . matchingEntries . map ( ( entry ) => entry . rowId ) ) . toEqual ( [ "plan-row" ] ) ;
408+ expect ( previousState . matchingEntries . map ( ( entry ) => entry . rowId ) ) . toEqual ( [
409+ "assistant-markdown-row" ,
410+ "plan-row" ,
411+ ] ) ;
303412 expect ( nextState . results ) . toEqual ( findThreadSearchResultsFromIndex ( index , "e" ) ) ;
304413 } ) ;
305414} ) ;
0 commit comments