Task panel never re-reads ~/.claude/tasks, so the plan the user sees and the plan on disk silently diverge
Environment
- Claude Code 2.1.197, desktop app on Windows 10 Enterprise (19043)
- Model: Opus 5
Summary
Three separate problems with the task/plan list, all hit in the same two sessions. The first one is the painful one: the task panel keeps its list in memory and never re-reads ~/.claude/tasks/<session-id>/, so the UI and the on-disk state diverge with no way to reconcile them short of restarting the session.
---
1. The panel does not reflect on-disk task state
TaskCreate / TaskUpdate write JSON files under ~/.claude/tasks/<session-id>/. Those writes succeed, and the tool results confirm them, but the panel keeps showing an older list.
Steps to reproduce
- In a session, create several tasks with
TaskCreate. - Delete some with
TaskUpdate(status: "deleted") and create replacements. - Compare the panel against
~/.claude/tasks/<session-id>/*.json.
Expected: the panel shows what is on disk.
Actual: the panel keeps the stale list. Deleting the files by hand does not change it either — the panel is not reading them at all.
In my case the disk ended up with ids 1..6 and 8 in the correct states, while the panel kept showing an older set. TaskList from the model side returns the correct, on-disk list — so the model and the user are looking at different things, which is the worst part: I could not tell the user what they were seeing.
The only workaround I found was restarting the session (/clear), which destroys the conversation. That is a bad trade for a display refresh, and it is what actually happened to this user: they ran /clear on my suggestion and lost a long working session. If the panel cannot re-read from disk, at least a manual refresh that does not nuke the context would help.
2. TaskUpdate can add a dependency but cannot remove one
The schema has addBlocks and addBlockedBy, and no counterpart to remove. To clear a blockedBy you have to delete the task and recreate it, which burns the id and leaves a visible gap in the numbering (my list went ...#6, #8 because #7 had to be thrown away just to drop one dependency).
A removeBlocks / removeBlockedBy pair — or allowing blockedBy to be set outright — would avoid this.
3. Session id changed mid-conversation, and TaskList silently went empty
Lower confidence on this one, observed once and I could not reproduce it deliberately. During one conversation the task directory in use changed from one session id to another. TaskList started returning an empty list because it reads the current session's folder, which was now a different, empty directory. The conversation itself continued normally, so only the task state was affected. There was no error and no warning — the list just looked like it had been wiped.
If the session id can legitimately change (reconnect, app restart), the task directory should follow it, or the tool should say that it is reading a directory that was just created.
---
Why it matters
Tasks are the shared view between the user and the model during long sessions. When that view silently diverges, the user sees a wrong plan, the model reports a different one, and neither can prove which is right without going to the filesystem. Everything else degrades from there.