Skip to content

fix(grok): surface plan mode approval in proposed plan cards - #5409

Open
ahmed-besic wants to merge 3 commits into
pingdotgg:mainfrom
ahmed-besic:fix/grok-plan-mode-approval
Open

fix(grok): surface plan mode approval in proposed plan cards#5409
ahmed-besic wants to merge 3 commits into
pingdotgg:mainfrom
ahmed-besic:fix/grok-plan-mode-approval

Conversation

@ahmed-besic

@ahmed-besic ahmed-besic commented Aug 5, 2026

Copy link
Copy Markdown

What Changed

When Grok Build enters plan mode, it writes plan.md and then calls exit_plan_mode. That tool is intercepted and reverse-RPCs the client over ACP as _x.ai/exit_plan_mode / x.ai/exit_plan_mode with planContent, 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:

  • Registers handlers for x.ai/exit_plan_mode and _x.ai/exit_plan_mode
  • Emits turn.proposed.completed with the plan markdown so the existing proposed-plan card appears
  • Responds with outcome: "abandoned" plus a client-capture message so the native gate unblocks without auto-implementing (same idea as Claude's ExitPlanMode capture)
  • Also promotes mid-plan plan.md writes (tool_call / tool_call_update targeting …/plan.md) into the same proposed-plan path so the card updates while plan mode is still active

Why

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 stdio 0.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.

  • Before: Grok plan mode hangs after writing the plan; no plan card; conversation cannot continue without approving in the Grok TUI.
  • After: As plan.md is written, the plan card appears and updates. On exit_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
  • Live ACP probe: _x.ai/exit_plan_mode payload + abandoned response unblocks the prompt
  • Manual T3 web UI (AeroSpace / grok-4.5): plan mode write surfaces the plan card; exit no longer stalls the thread

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes (happy to add after a UI smoke against a Grok plan-mode thread)
  • A video is not applicable (no animation/timing change)

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_mode and turns Grok session plan.md writes into the same turn.proposed.completed path Claude/Cursor already use for proposed-plan cards.

The adapter registers x.ai/exit_plan_mode and _x.ai/exit_plan_mode, pulls markdown via extractXAiExitPlanMarkdown (with fallback to the last seen plan.md body), emits turn.proposed.completed, and replies with outcome: "abandoned" so the native Grok approval gate does not block the turn. ToolCallUpdated events that write ~/.grok/sessions/.../plan.md are promoted the same way while plan mode is still active; isGrokPlanMarkdownPath ignores repo plan.md files.

Session state tracks lastKnownProposedPlanMarkdown for deduping and fallbacks, and clears it on new turns and turn settlement so stale plans cannot reappear. XAiAcpExtension adds 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

  • Adds isGrokEnterPlanModeToolCall to detect when Grok enters plan mode from ToolCallUpdated events, and sets a planModeActive flag on the session context.
  • While plan mode is active, writes to Grok's session plan.md (detected via isGrokPlanMarkdownPath) are extracted and emitted as turn.proposed.completed events.
  • Handles x.ai/exit_plan_mode ext requests in makeGrokAdapter by emitting a turn.proposed.completed event with the plan markdown and responding with an abandoned outcome to unblock the turn.
  • Deduplicates identical plan markdown per turn and clears plan state at turn end and at the start of each new turn.
  • Adds supporting utilities in XAiAcpExtension.ts for parsing exit_plan_mode payloads, building abandoned responses, and extracting plan markdown from tool call diffs.

Macroscope summarized d0959e3.

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.
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2db0d743-3bc6-428c-ac57-30d1ab372ee7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 5, 2026
Comment thread apps/server/src/provider/Layers/GrokAdapter.ts
Comment thread apps/server/src/provider/acp/XAiAcpExtension.ts Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.

Fix All in Cursor

❌ 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.

Comment thread apps/server/src/provider/Layers/GrokAdapter.ts
payload: event.rawPayload,
},
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit a5b1757. Configure here.

Comment thread apps/server/src/provider/acp/XAiAcpExtension.ts
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.
@macroscopeapp

macroscopeapp Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant