Skip to content

fix: prevent stale todo list from overwriting current state#301623

Closed
pdrgds wants to merge 3 commits intomicrosoft:mainfrom
pdrgds:fix/chat-todo-list-stale-hydration-299234
Closed

fix: prevent stale todo list from overwriting current state#301623
pdrgds wants to merge 3 commits intomicrosoft:mainfrom
pdrgds:fix/chat-todo-list-stale-hydration-299234

Conversation

@pdrgds
Copy link

@pdrgds pdrgds commented Mar 13, 2026

Summary

Fixes #299234

  • Root cause: ChatToolInvocationPart's constructor called setTodos() from toolSpecificData on every render. When parts were constructed out of chronological order (lazy rendering, collapsed sections, scroll virtualization), an older invocation's data overwrote the current state.
  • Fix: Remove the setTodos() side-effect from the UI constructor. Move todo list hydration to the two proper data entry points in ChatModel:
    • _deserializeRequest() — for session restore from storage (scans all parts, hydrates only the latest)
    • acceptResponseProgress() — for live background agent data arriving via toolInvocationSerialized

Test plan

  • Regression test: chatToolInvocationPart.test.ts — instantiates real ChatToolInvocationPart with stale todoList data, asserts setTodos is not called. Fails on main, passes on this branch.
  • Hydration tests: chatModel.test.ts — verifies deserialization hydrates todo list correctly (single and multiple invocations, latest state wins)
  • Invocation tests: manageTodoListTool.test.ts — write/read operations, pastTenseMessage generation, steering mid-task consistency
  • All existing tests pass (17919 passing, 19 pre-existing failures)
  • TypeScript compilation clean

pdrgds added 2 commits March 13, 2026 19:16
…crosoft#299234)

ChatToolInvocationPart's constructor called setTodos() from
toolSpecificData on every render. When parts were constructed out of
chronological order (lazy rendering, collapsed sections, scroll
virtualization), an older invocation's data overwrote the current state.

Move todo list hydration from the UI part constructor to the two proper
data entry points in ChatModel: _deserializeRequest() for session
restore and acceptResponseProgress() for live background agent data.
…crosoft#299234)

- Extract shared `deserializeTodoList()` helper to eliminate duplicated
  mapping logic between deserialization and acceptResponseProgress paths
- Tighten multi-request deserialization test to assert exact call count
  and verify both intermediate and final hydration states
- Add test for acceptResponseProgress runtime hydration path
@pdrgds
Copy link
Author

pdrgds commented Mar 14, 2026

Closing this PR while seeking guidance on the preferred approach. See my comment on #299234 for two alternative fix strategies.

@pdrgds pdrgds closed this Mar 14, 2026
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.

Chat incorrectly reports TODO list as completed while UI shows otherwise

2 participants