VS Code: plan review pane shows previous plan version when ExitPlanMode is batched with a plan-file write
Summary
In the VS Code extension, the plan review pane ("Ready for review") can show the previous version of the plan when the model writes the plan file and calls ExitPlanMode in the same tool batch. The approval result contains the new plan, so the user reviews one plan and approves another.
Environment
- VS Code 1.139.1 (macOS, arm64)
- Extension
anthropic.claude-code2.1.283 (darwin-arm64), with its bundled CLI
Steps to reproduce
- In plan mode, let the model revise an existing plan.
- The model emits a
Write(orEdit) to the plan file andExitPlanModein the same parallel tool batch. - Look at the "Ready for review" pane.
Expected
The pane shows the plan as written by that batch, which is what the user is approving.
Actual
The pane shows the plan as it was before that write. The ExitPlanMode result (the "Approved Plan" text) contains the new version, so what was reviewed and what was approved differ.
Evidence
From Claude VSCode.log: the content of each open_markdown_preview request, compared with the plan on disk at that moment.
| Time | Content sent to pane | Plan on disk | Tool calls |
|---|---|---|---|
| 09:00:51 | previous plan (v0) | v1 | Write + ExitPlanMode, same batch |
| 09:01:41 | v1 | v1 + title edit | Edit + ExitPlanMode, same batch |
| 09:05:31 | v1 + title edit | v2 | Write + ExitPlanMode, same batch |
| 09:09:27 | v2 | v2 ✅ | ExitPlanMode alone |
| 09:13:48 | v2 | v3 | Write + ExitPlanMode, same batch |
The pane lags exactly one version every time the write is batched with ExitPlanMode. It's correct when ExitPlanMode is sent on its own.
Suspected cause
ExitPlanMode's plan field is injected by normalizeToolInput ("The plan content (injected by normalizeToolInput from disk)"), via the plan-file cache. The injection appears to happen before the sibling Write/Edit in the same batch executes, so the snapshot is stale. The webview then forwards permissionRequest.inputs.plan to openMarkdownPreview, which renders it as-is.
Possible fixes:
- Resolve
planwhen the permission prompt is shown, after earlier tool calls in the batch have completed. - Or re-read the plan file when rendering the preview.
Side note (possibly unrelated)
In the extension host, shutdown() sets planPreviewsDetached = true, and nothing appears to reset it. It also detach()es the open preview panels without disposing them. If the same host object is reused afterwards, openMarkdownPreview would return early and leave a stale panel on screen. This didn't cause the case above, because the log shows the requests were received, but it may be worth checking.