fix(grok): surface plan mode approval in proposed plan cards - #5409
fix(grok): surface plan mode approval in proposed plan cards#5409ahmed-besic wants to merge 3 commits into
Conversation
Grok intercepts exit_plan_mode and reverse-RPCs the client for approval. Without a handler the turn hung and plan.md was invisible in T3. Capture plan.md writes and x.ai/exit_plan_mode into turn.proposed.completed, then abandon the native gate so the existing plan card can finish the flow.
|
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 Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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 |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a5b1757. Configure here.
| payload: event.rawPayload, | ||
| }, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Shared stamp for two events
Medium Severity
On ToolCallUpdated, the tool lifecycle event and the derived turn.proposed.completed event both reuse the same stamp, so they share one eventId. The exit-plan path correctly allocates a fresh stamp. Duplicate runtime event IDs break the uniqueness invariant used for activity IDs and command tagging.
Reviewed by Cursor Bugbot for commit a5b1757. Configure here.
Clear lastKnownProposedPlanMarkdown on new turns and settlement so an empty exit_plan_mode cannot re-surface a previous plan. Restrict plan.md detection to paths under .grok/sessions so workspace plan.md files are not promoted to proposed plans.
Scope proposed-plan dedupe to the current turn so re-proposing the same text later still emits a card. Use a fresh event stamp when promoting plan.md writes (avoid shared eventIds with tool lifecycle events). Only promote session plan.md while plan mode is active after enter_plan_mode.
ApprovabilityVerdict: Needs human review This PR introduces new feature capability for surfacing Grok plan mode approval in T3's proposed plan cards, adding new state management, event handling, and ACP extension handlers. Additionally, an unresolved review comment identifies a potential bug with duplicate event IDs that should be addressed. You can customize Macroscope's approvability policy. Learn more. |


What Changed
When Grok Build enters plan mode, it writes
plan.mdand then callsexit_plan_mode. That tool is intercepted and reverse-RPCs the client over ACP as_x.ai/exit_plan_mode/x.ai/exit_plan_modewithplanContent, expecting the TUI plan approval window (approve / request changes / abandon).T3 never handled that extension method, so the turn stalled with no UI, and the plan content never showed up as a proposed plan. Users had to open the same session in the Grok terminal and approve there to continue.
This:
x.ai/exit_plan_modeand_x.ai/exit_plan_modeturn.proposed.completedwith the plan markdown so the existing proposed-plan card appearsoutcome: "abandoned"plus a client-capture message so the native gate unblocks without auto-implementing (same idea as Claude's ExitPlanMode capture)plan.mdwrites (tool_call / tool_call_update targeting…/plan.md) into the same proposed-plan path so the card updates while plan mode is still activeWhy
Grok threads that entered plan mode looked dead: no output, no approval UI, and no way to continue without leaving T3. Claude already maps ExitPlanMode into proposed plans; Cursor maps
cursor/create_plan. Grok needed the same product path for its xAI extension method.Live probe against
grok agent stdio0.2.118 confirmed the wire shape:{ sessionId, toolCallId, planContent }and a successful unblock with{ outcome: "abandoned", feedback }.UI Changes
Uses the existing proposed plan card — no new UI components.
plan.mdis written, the plan card appears and updates. Onexit_plan_mode, the turn finishes and the card stays actionable (implement / follow-up) like Claude/Cursor plans.Validation
vp test run src/provider/acp/XAiAcpExtension.test.ts src/provider/Layers/GrokAdapter.test.ts— 35 passed_x.ai/exit_plan_modepayload + abandoned response unblocks the promptChecklist
Made by Grok Build via the Grok Build harness while working on T3 Code.
Note
Medium Risk
Changes Grok ACP extension handling and turn lifecycle around plan capture; behavior is covered by new adapter and extension tests but affects provider runtime event flow users rely on during plan mode.
Overview
Grok plan mode no longer stalls: the adapter handles xAI
exit_plan_modeand turns Grok sessionplan.mdwrites into the sameturn.proposed.completedpath Claude/Cursor already use for proposed-plan cards.The adapter registers
x.ai/exit_plan_modeand_x.ai/exit_plan_mode, pulls markdown viaextractXAiExitPlanMarkdown(with fallback to the last seenplan.mdbody), emitsturn.proposed.completed, and replies withoutcome: "abandoned"so the native Grok approval gate does not block the turn.ToolCallUpdatedevents that write~/.grok/sessions/.../plan.mdare promoted the same way while plan mode is still active;isGrokPlanMarkdownPathignores repoplan.mdfiles.Session state tracks
lastKnownProposedPlanMarkdownfor deduping and fallbacks, and clears it on new turns and turn settlement so stale plans cannot reappear.XAiAcpExtensionadds schemas/helpers and unit tests; the mock ACP agent adds env flags for integration tests.Reviewed by Cursor Bugbot for commit 511e92b. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Surface Grok plan mode approvals as proposed plan cards in the ACP adapter
isGrokEnterPlanModeToolCallto detect when Grok enters plan mode fromToolCallUpdatedevents, and sets aplanModeActiveflag on the session context.plan.md(detected viaisGrokPlanMarkdownPath) are extracted and emitted asturn.proposed.completedevents.x.ai/exit_plan_modeext requests inmakeGrokAdapterby emitting aturn.proposed.completedevent with the plan markdown and responding with anabandonedoutcome to unblock the turn.XAiAcpExtension.tsfor parsing exit_plan_mode payloads, building abandoned responses, and extracting plan markdown from tool call diffs.Macroscope summarized d0959e3.