Skip to content

fix(plan): Show implementation suggestions only when LLM has all the information#6240

Merged
alex-alecu merged 4 commits intomainfrom
fix/fix-plan-mode-suggestions
Feb 25, 2026
Merged

fix(plan): Show implementation suggestions only when LLM has all the information#6240
alex-alecu merged 4 commits intomainfrom
fix/fix-plan-mode-suggestions

Conversation

@alex-alecu
Copy link
Contributor

@alex-alecu alex-alecu commented Feb 24, 2026

Context

#6218
#6143

This PR #6007 introduced suggestions after planning (similar to what Claude Code does), but sometimes the LLM expects some answers from the user and instead of showing just the input text, we display the implement suggestions.

We need to show the implement suggestions only when we are 100% sure we have all the info necessary.

Implementation

Move out of experimental the tool call plan_exit. We can add another tool call, but since we already have this in place, we might just as well use it.

When plan_exit is called, the LLM is sure the plan is ready in its opinion. We add the suggestions to start the implementation only when plan_exit is invoked.

Screenshots

Screenshot 2026-02-25 at 09 36 43

Users are choosing ~equally all options at the moment. After this change we should show less custom/dismiss in posthog

Screenshot 2026-02-25 at 11 15 35

How to Test

Ask the CLI to add a greetings prompt when Kilo is opened while in PLAN mode. Look for the implement suggestions at the end.

Get in Touch

We'd love to have a way to chat with you about your changes if necessary. If you're in the Kilo Code Discord, please share your handle here.

@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Feb 25, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Overview

This PR refactors the plan_exit flow from a tool-driven user prompt into a clean signal-based architecture:

  1. PlanExitTool simplified — No longer prompts the user or injects synthetic messages. It now returns a simple completion signal with plan metadata.
  2. shouldAskPlanFollowup extracted — A shared predicate in SessionPrompt that checks for a completed plan_exit tool part in messages after the last user message. This replaces the previous lastUser.agent === "plan" check with explicit tool detection.
  3. resolvePlan added — Multi-strategy plan text resolution with a well-ordered fallback chain: last assistant text → all assistant texts after last user → plan file on disk.
  4. Prompt sync improved — The TUI prompt component now syncs on [sessionID, msg.id] instead of just sessionID, correctly re-syncing when a new synthetic user message appears (e.g., "Implement the plan above").
  5. PlanExitTool always registered — Removed feature flag gating from the registry; access is properly controlled via agent permissions (deny by default, allow only for plan agent).
  6. TUI session handler cleaned upplan_exit no longer triggers agent switching in the session route; PlanFollowup handles the transition.
  7. Comprehensive test coverage — New plan-exit-detection.test.ts covers trigger detection, continue/reject flows, non-completed status, multi-message scenarios, and plan file fallback. Registry test confirms plan_exit is always available.

The permission model is sound: plan_exit is deny by default in agent config, allow only for the plan agent, and shouldAskPlanFollowup additionally gates on ["cli", "vscode"].includes(Flag.KILO_CLIENT). The resolvePlan fallback chain handles edge cases well (empty last assistant, tool-only turns, missing plan text).

Files Reviewed (8 files)
  • packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx — Prompt sync key change
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx — Removed plan_exit agent switch
  • packages/opencode/src/kilocode/plan-followup.ts — Added resolvePlan, updated ask() to use it
  • packages/opencode/src/session/prompt.ts — Extracted shouldAskPlanFollowup, updated loop
  • packages/opencode/src/session/prompt/plan.txt — Added plan_exit instruction
  • packages/opencode/src/tool/plan-exit.txt — Updated description
  • packages/opencode/src/tool/plan.ts — Simplified PlanExitTool
  • packages/opencode/src/tool/registry.ts — Always register PlanExitTool
  • packages/opencode/test/kilocode/plan-exit-detection.test.ts — New comprehensive test file
  • packages/opencode/test/tool/registry.test.ts — New plan_exit registry test

...(config.experimental?.batch_tool === true ? [BatchTool] : []),
...(Flag.KILO_EXPERIMENTAL_PLAN_MODE && Flag.KILO_CLIENT === "cli" ? [PlanExitTool, PlanEnterTool] : []),
PlanExitTool, // kilocode_change - always registered; gated by agent permission instead
...(Flag.KILO_EXPERIMENTAL_PLAN_MODE && Flag.KILO_CLIENT === "cli" ? [PlanEnterTool] : []),
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about desktop and other clients, or is that irrelevant? What about extension next?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will handle them manually in a feature PR, I have not tested them yet


// Fall back to plan file on disk
const session = await Session.get(input.sessionID)
const file = Bun.file(Session.plan(session))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we read the complete plan always? Also if it's really large? Could that be the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The plan will rarely be large, it can still happen

Comment on lines +120 to +121
PlanExitTool, // kilocode_change - always registered; gated by agent permission instead
...(Flag.KILO_EXPERIMENTAL_PLAN_MODE && Flag.KILO_CLIENT === "cli" ? [PlanEnterTool] : []),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is PlanEnterTool experimental and PlanExitTool not? Wondering what happens if the flag is triggered by the users

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@marius-kilocode PlanExitTool was experimental too before this PR - I am not sure why, but I though it's a good candidate for this issue.

Copy link
Collaborator

Choose a reason for hiding this comment

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

So what if the flag is enabled or disabled, will planning be broken?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

PlanExitTool was promoted from experimental to to standard, so the flag KILO_EXPERIMENTAL_PLAN_MODE will do nothing for it.

@alex-alecu alex-alecu merged commit d8ce43f into main Feb 25, 2026
10 checks passed
@alex-alecu alex-alecu deleted the fix/fix-plan-mode-suggestions branch February 25, 2026 10:18
alex-alecu added a commit that referenced this pull request Mar 6, 2026
A merge conflict resolution incorrectly gated PlanExitTool behind
KILO_EXPERIMENTAL_PLAN_MODE && KILO_CLIENT === "cli", preventing the
plan agent from signaling completion. This broke the "looks good,
implement" flow — the follow-up prompt never appeared and no new
code-mode session was created.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants