fix(server): handle proposed_plan fallback after mode switch#2455
fix(server): handle proposed_plan fallback after mode switch#2455pedrokpp wants to merge 4 commits intopingdotgg:mainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review This PR introduces new runtime behavior for extracting proposed plans from assistant message text via XML tag parsing. The changes affect multiple message finalization paths in core orchestration logic, warranting human review. You can customize Macroscope's approvability policy. Learn more. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 29b428d. Configure here.

What Changed
This fixes proposed-plan rendering when a user starts in Plan mode, switches the same thread back to Build mode, and then asks for another plan.
On the server side, proposed-plan fallback extraction now runs when an assistant message completes with
<proposed_plan>...</proposed_plan>in its final text, even if the provider did not emit a canonicalturn.proposed.completedevent.When that happens, T3 Code now:
<proposed_plan><proposed_plan>block out of the visible assistant chat message so the raw tagged text is not rendered alongside the plan cardAs a result, the Build-mode fallback now behaves like a normal proposed plan:
Regression coverage was added around assistant-message completion so the plan is projected correctly and the assistant message is suppressed visually while preserving the turn bookkeeping required by the follow-up UI.
Why
There was a mode-transition bug in the Codex flow:
In that path, the provider could return a
<proposed_plan>block as ordinary assistant text instead of emitting the canonical proposed-plan event.Before this fix, the UI could render the raw tagged markdown as a normal assistant message, or render both the raw tagged message and the proposed plan card at the same time. A follow-up regression also showed that suppressing the assistant text too aggressively could break the normal
Implementflow when switching back to Plan mode.That behavior was incorrect. Proposed-plan blocks should project as first-class proposed plans, the raw tagged payload should not remain in the chat transcript when it only exists to back the plan card, and the resulting plan should still behave like a normal actionable plan afterward.
This server-side fallback is the smallest fix because it reuses the existing proposed-plan projection pipeline instead of changing web rendering rules or broader mode behavior.
UI Changes
Before

After


Repro shown in before/after:
<proposed_plan>text in chat before this fixChecklist
Note
Medium Risk
Touches
ProviderRuntimeIngestionmessage finalization/proposed-plan projection, which can affect chat transcript rendering and plan upsert behavior across turn/approval boundaries, but is scoped and covered by new tests.Overview
Ensures proposed plans still project when providers return a
<proposed_plan>...</proposed_plan>block as plain assistant text (e.g., after mode switches), by extracting the block on assistant completion and upserting it intothread.proposedPlans.finalizeAssistantMessagenow strips<proposed_plan>blocks from emitted assistant deltas, still completes the assistant message even if the visible text becomes empty, and returns the raw text so callers can derive fallback plan markdown; this fallback projection is triggered onitem.completed,turn.completed, and approval-boundary finalization.Adds regression tests covering plan extraction from tagged assistant text on message completion, turn completion, and buffered text flushed at
request.opened.Reviewed by Cursor Bugbot for commit bbc954c. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix
proposed_planblock handling in assistant messages after mode switch<proposed_plan>blocks embedded in assistant message text using two new regex constants and a helper in ProviderRuntimeIngestion.ts.<proposed_plan>content from assistant message deltas so plan markup is never rendered as chat text; instead, aproposedPlanentity is projected for the active turn.assistant.message.completed,turn.completed, andrequest.opened(pause boundary) — each now extracts and finalizes any buffered proposed plan.assistant.completeis now emitted even when visible text is empty, as long as raw content (e.g. a plan block) was present.Macroscope summarized bbc954c.