| ... | @@ -382,6 +382,60 @@ describe("computeStableMessagesTimelineRows", () => { | ... | @@ -382,6 +382,60 @@ describe("computeStableMessagesTimelineRows", () => { |
| 382 | expect(repeated.result).toBe(initial.result); | 382 | expect(repeated.result).toBe(initial.result); |
| 383 | }); | 383 | }); |
| 384 | | 384 | |
| | 385 | it("reuses work rows when equivalent timeline derivations create new grouped arrays", () => { |
| | 386 | const firstWorkEntry = { |
| | 387 | id: "work-1", |
| | 388 | createdAt: "2026-01-01T00:00:00Z", |
| | 389 | label: "thinking", |
| | 390 | detail: "Inspecting repository state", |
| | 391 | tone: "thinking" as const, |
| | 392 | }; |
| | 393 | const secondWorkEntry = { |
| | 394 | id: "work-2", |
| | 395 | createdAt: "2026-01-01T00:00:01Z", |
| | 396 | label: "read", |
| | 397 | detail: "Reading package.json", |
| | 398 | tone: "tool" as const, |
| | 399 | }; |
| | 400 | |
| | 401 | const createRows = () => |
| | 402 | deriveMessagesTimelineRows({ |
| | 403 | timelineEntries: [ |
| | 404 | { |
| | 405 | id: "entry-work-1", |
| | 406 | kind: "work", |
| | 407 | createdAt: firstWorkEntry.createdAt, |
| | 408 | entry: firstWorkEntry, |
| | 409 | }, |
| | 410 | { |
| | 411 | id: "entry-work-2", |
| | 412 | kind: "work", |
| | 413 | createdAt: secondWorkEntry.createdAt, |
| | 414 | entry: secondWorkEntry, |
| | 415 | }, |
| | 416 | ], |
| | 417 | completionDividerBeforeEntryId: null, |
| | 418 | isWorking: false, |
| | 419 | activeTurnStartedAt: null, |
| | 420 | turnDiffSummaryByAssistantMessageId: new Map(), |
| | 421 | revertTurnCountByUserMessageId: new Map(), |
| | 422 | }); |
| | 423 | |
| | 424 | const firstRows = createRows(); |
| | 425 | const initial = computeStableMessagesTimelineRows(firstRows, { |
| | 426 | byId: new Map(), |
| | 427 | result: [], |
| | 428 | }); |
| | 429 | const secondRows = createRows(); |
| | 430 | |
| | 431 | expect(secondRows[0]).not.toBe(firstRows[0]); |
| | 432 | |
| | 433 | const repeated = computeStableMessagesTimelineRows(secondRows, initial); |
| | 434 | |
| | 435 | expect(repeated).toBe(initial); |
| | 436 | expect(repeated.result[0]).toBe(initial.result[0]); |
| | 437 | }); |
| | 438 | |
| 385 | it("returns a new result when row order changes without content changes", () => { | 439 | it("returns a new result when row order changes without content changes", () => { |
| 386 | const firstUserMessage = { | 440 | const firstUserMessage = { |
| 387 | id: "user-1" as never, | 441 | id: "user-1" as never, |