fix(agent): seed agent todoState from plan-seed so complete_step advances counter#4230
Closed
ashishexee wants to merge 1 commit into
Closed
fix(agent): seed agent todoState from plan-seed so complete_step advances counter#4230ashishexee wants to merge 1 commit into
ashishexee wants to merge 1 commit into
Conversation
…nces counter Fixes esengine#4176 When a plan is approved, the controller emits a plan-seed todo_write event (frontend shows the list) but did not initialize the agent's todoState. The agent's todoState is only set when the model calls todo_write itself, which it may skip since the plan-seed already displays the list. When the model then calls complete_step, advanceCanonicalTodo checks len(todoState) == 0 and returns early — no synthetic todo_write event is emitted, so the frontend counter stays at 0/x. Fix: after seedPlanTodos emits the plan-seed events, also call the new Agent.SeedTodoState() to initialize the agent's canonical todo list from the parsed plan. SeedTodoState is a no-op when the agent already has a todoState (e.g. the model already called todo_write), avoiding overwrites.
ee1ca5c to
bddaa21
Compare
This was referenced Jun 13, 2026
Collaborator
|
Thanks again for this contribution. I opened #4313 as an integration PR that includes this PR's plan-seed fix: approved plan todos now seed the agent's canonical #4313 combines that contribution with the related restored-history and completed-panel work from #4159, #4271, and #4309, plus the additional success/error replay guards found during review. To keep review focused, I’m closing this PR as superseded by #4313. You are credited in the integration commit and PR body. |
esengine
pushed a commit
that referenced
this pull request
Jun 14, 2026
…#4313) Seed the agent's canonical todo state from approved plans so later complete_step calls advance the visible panel, and rebuild restored desktop history by replaying todo_write/complete_step only on explicitly successful tool results (missing or errored results no longer count as completed). Hide the panel once all todos are done, keyed to stable content rather than array identity. Integrates #4159, #4230, #4271, and #4309. Closes #4259 Closes #4105 Closes #4170 Closes #4241 Co-authored-by: JesonChou <51042251+JesonChou@users.noreply.github.com> Co-authored-by: ashishexee <144021866+ashishexee@users.noreply.github.com> Co-authored-by: GTC2080 <140309575+GTC2080@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4170
Also addresses #4169 (UI shows only 1 completion instead of all).
Problem
When a plan is approved, the controller emits a
plan-seedtodo_writeevent so the frontend task panel populates immediately. However, the controller did not initialize the agent'stodoState— that internal state is only set when the model callstodo_writeitself.Since the plan-seed already displays the list, the model often skips calling
todo_writeand goes straight tocomplete_step. Whencomplete_stepruns,advanceCanonicalTodocheckslen(todoState) == 0and returns early — no synthetictodo_writeupdate event is emitted, so the frontend counter stays at0/x.Root Cause
seedPlanTodosincontroller.goemits UI events but does not initialize the agent's canonical todo state. The agent and the frontend were out of sync: the frontend had the list, but the agent did not.Fix
Agent.SeedTodoState()— new public method that initializestodoStatewhen empty (no-op if already set, so a model's owntodo_writeis never overwritten)Controller.seedAgentTodoState()— parses the plan-seed args into[]evidence.TodoItemand callsSeedTodoStateseedPlanTodosafter emitting the plan-seed eventsNow when
complete_stepruns after a plan-seed:todoStateis populated →advanceCanonicalTodofinds the matching itemtodo_writeemitted1/5 → 2/5 → ... → 5/5Tests
TestSeedTodoState— seeds empty agentTestSeedTodoStateNoOverwrite— no-op when agent already has stateTestSeedTodoStateAllowsAdvanceAfterSeed— proves the full flow: seed → advance → counter updatesTestSeedPlanTodosSeedsAgentState— controller integration: plan-seed also seeds agentTestSeedPlanTodosEmptyPlanNoOp— empty plan is a no-opFiles Changed
internal/agent/agent.go—SeedTodoState()methodinternal/agent/canonical_todo_test.go— 3 new agent testsinternal/control/controller.go—seedAgentTodoState()helper + call fromseedPlanTodosinternal/control/plan_seed_test.go— 2 new controller tests