Pi Plan Mode
Enhance pi's Plan Mode extension with revision-bound approval, interactive and RPC controls, exact tool restoration, and normal session resume.
Let me approve the exact plan Pi will execute
I use Pi's Plan Mode extension to explore a repository before making changes. I want to review a plan and approve that specific version, both interactively and through RPC. If the agent revises it while I'm deciding, my old approval must not authorize the new plan. Reopening a session must not grant approval or start execution again.
Have the agent submit plans explicitly with plan_submit({ steps: string[] }), available only while planning. Require at least one step, with non-whitespace content in every step, preserve the supplied strings, and replace the draft on every valid submission, advancing its revision even if the text is unchanged. Invalid submissions should fail as tool errors (pi's isError result) without changing the draft. Ordinary prose, including Plan: sections or approval-looking text, must not submit or approve anything. Keep Pi's normal tool-argument handling.
Keep /plan, the existing shortcut, --plan and /todos. Entering planning again should preserve the current draft and tool selection, never toggle writing back on. When already planning and idle, either acknowledge the no-op or report that planning is already active; preserve state, tools and model-call count in either case. Starting another cycle after approval should create a fresh plan identity with an empty draft and no inherited approval. Let me choose Execute, Stay or Refine once a submitted plan settles. The open choice must not block Pi: while it is open, other prompts (for example over RPC) run normally and may revise the draft, and Execute must still refer to the version I was shown. Stay and Refine must keep planning restrictions. /todos and [DONE:n] should still show progress without changing the authoritative plan or its approval.
While planning, allow only plan_submit and whichever of read, grep, find and ls were already active. Block Bash, edit, write and custom tools even when the model tries to call them directly. Approval should restore exactly my original tool selection, including custom tools. Entering or approving must reject while Pi is busy or has pending messages; mode controls must not interrupt an in-flight tool batch.
Through the control interface, only interactive or rpc user input may enter or approve a plan. Reject other sources for these changes, and never treat assistant messages or tool output as approval. An approval must match the current session, plan and submitted revision; reject an empty draft, a different identity, and older or future revisions without changing state or tools. Successful approval should retain the approved snapshot, restore the tools and automatically start one execution request containing that exact identity and every step, without another user message. Repeating the same approval while idle should succeed without starting another request. While that approved execution is still busy, a matching duplicate may either acknowledge the existing approval or report busy; neither response may change the snapshot or start another request. Keep the snapshot identifiable after execution settles.
I need /plan-control enter, /plan-control status and /plan-control approve <sessionId> <planId> <revision> through Pi's normal input path in both modes. Expose state with sessionId, mode (normal, planning or approved), planId, revision and steps. Use stable opaque plan IDs and Pi's current session ID. For each control, append a plan-control-result custom session entry containing operation, ok and state; report a useful reason on rejection. A control with a missing, extra or invalid argument is malformed. For malformed controls, operation may name the attempted operation or a generic invalid-command category; it must be a nonempty string. Invalid controls must not reach the model or change plan state, and status must be read-only. Return submitted state as structured tool output, in JSON text or result details. Send a plan-approved custom message with the approved identity and steps in its details and model-visible content. Extra fields, error codes and presentation wording are up to you.
For an already-persisted file-backed session with an assistant reply, closing normally while idle and resuming in a new process should preserve the plan identity, draft, revision, approval and original tools. Planning must resume restricted; an approved plan must resume with restored tools and no execution replay. Ignore another session's state. --plan only applies when a new session starts: it starts planning on a fresh session (one with no assistant reply yet, even if Pi already recorded metadata such as the model), and it is ignored when an existing session with an assistant reply is resumed, which keeps its saved state (a session that never entered planning resumes in normal mode). Crash recovery, shutdown during execution, fork/tree navigation, extension reload, isolation from malicious extension code or external processes, and enforcing the model's semantic compliance with the plan are out of scope.
Update only packages/coding-agent/examples/extensions/plan-mode/, its README and relevant tests, using the public extension API and retaining its loadable default export. You may update plan-mode-extension.test.ts and plan-mode-utils.test.ts, and add coding-agent tests; preserve utility behavior and unrelated regressions. The evaluator runs an independent copy of the original utility tests. Other existing test files must remain unchanged. Leave core, other extensions, dependencies and build configuration unchanged. Work offline with the installed tools.