↓ Skip to main content
The Discrete State Machine of Plan Mode: Decision Tree Pruning, Backtracking Costs, and Diminishing Returns
  1. Posts/

The Discrete State Machine of Plan Mode: Decision Tree Pruning, Backtracking Costs, and Diminishing Returns

Claude Code Source Code Deconstruction - This article is part of a series.
Part : This Article

Autoregressive large language models operating in unconstrained environments suffer from an inherent tendency toward myopic mutation and runaway divergence. Claude Code’s Plan Mode attaches an external discrete Finite State Machine (FSM) that projects the action space onto a strictly side-effect-free subset, using an interactive human barrier to prune catastrophic physical backtracking branches from the decision tree.

In disciplined software engineering, experienced developers instinctively value structural planning: mapping dependency graphs, deriving type signatures, and scoping blast radiuses before modifying a single line of code. Large language models possess no such innate restraint. Shaped by reinforcement learning to generate immediate answers, an agent granted unrestrained write permissions will instinctively mutate files without global context, precipitating an architectural cascade across complex repositories.

Action Myopia and the Divergence of Markov Decision Trees
#

When an agent tackles a coding assignment formulated as a Markov Decision Process (MDP), each autoregressive tool dispatch traverses a branching trajectory. The cumulative probability of the system maintaining global alignment through step $T$ degrades according to cascading error probabilities:

$$P(\text{Success}_T) = \prod_{t=1}^T (1 - \epsilon_t)$$

Even if the individual error rate $\epsilon_t$ of a single tool execution is kept down to a modest $5%$, after 15 consecutive autonomous mutations the cumulative probability of avoiding an off-target trajectory drops sharply:

$$P(\text{Success}_{15}) = (1 - 0.05)^{15} \approx 46.3\%$$

In an unconstrained read-write workspace, language models routinely fall into Action Myopia:

  1. Observing a broken test, the model immediately calls edit to alter function parameters.
  2. The change breaks upstream call sites; the model blindly issues write_file to override caller files.
  3. Transitive dependencies trigger secondary compilation errors, and the model scrambles outward across the codebase.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
                   [Root Goal: Refactor Auth Service]
                           /         \
                 (Disciplined Plan)   (Action Myopic Branch)
                      |                         |
             [Trace Dependency Graph]   [Instantly Edit Auth.ts]
                      |                         |
             [Establish API Contract]   [Break Token.ts Signature]
                      |                         |
             [Human Barrier Check]      [Mutate 8 Upstream Files]
                      |                         |
             (Zero-Cost Pruning)        (Physical Backtracking Disaster)

In real-world engineering, the penalty for this divergence is the Physical Backtracking Penalty. Once an agent scatters flawed edits across a dozen files, rolling back requires complicated Git resets, dirty working tree cleanups, and thousands of contrite, token-heavy recovery turns. As analyzed in The Physical Cost of Context Compression, this churn burns context budgets while polluting short-term reasoning memory.

Formalizing Plan Mode: A Finite State Machine with Barrier Synchronization
#

The architectural mechanism of Plan Mode is an external two-state Finite State Machine (FSM) wrapped around the agent loop:

$$\mathcal{S} \in \{\text{PLAN}, \text{EXECUTE}\}$$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
+------------------------------------------------------------+
|                Finite State Machine (FSM)                  |
|                                                            |
|       +----------------+            /plan command          |
|       |                | <--------------------------+      |
|       |   PLAN State   |                            |      |
|       | (Safe Read-Only|                            |      |
|       +-------+--------+                            |      |
|               |                                     |      |
|               | User Approves Plan (Barrier Sync)   |      |
|               v                                     |      |
|       +----------------+                            |      |
|       |  EXECUTE State | ---------------------------+      |
|       |  (Read/Write)  |                                   |
|       +----------------+                                   |
+------------------------------------------------------------+

1. Asymmetric Projection of Action Space
#

Let $\mathcal{A}$ denote the complete universe of dispatchable tools, encompassing all file writes, edits, and terminal execution vectors. Under the PLAN state, the runtime dispatch router forcibly projects the action space onto an immutable subset:

$$\mathcal{A}_{\text{plan}} = \mathcal{A} \cap \{\text{read\_file}, \text{glob}, \text{grep}, \text{ls}, \text{read\_only\_bash}\}$$

As detailed in Permissions and Real Security Boundaries, access control must intervene before operating system calls execute. In PLAN mode, any attempt by the model to dispatch a write_file or mutating shell command is trapped by the local dispatcher and returned as an error. This barrier originates from hard application-level routing.

2. Human Barrier Synchronization
#

The transition from PLAN to EXECUTE is non-autonomous; it introduces a mandatory human-in-the-loop synchronization barrier:

  • The agent conducts repository exploration under strict read-only constraints.
  • It consolidates findings into a structured Markdown document enumerating affected files, dependency shifts, and operational sequences.
  • The engine halts execution, suspending the loop until a human approves the proposal.

This barrier radically alters backtracking economics: rejecting an erroneous approach during Plan Mode costs only a single prompt (“Wrong approach; do not touch the database layer”) and a few discarded lines of text. Rejecting an approach during unconstrained execution requires reverting dirty files and reconciling corrupted repository states.

Plan Mode replaces expensive physical state rollback with low-cost textual pruning.

The Collapse of Static Planning: Fragility Against Dynamic Compilers
#

Treating Plan Mode as a panacea is dogmatic. Static upfront planning exhibits a severe defect when applied to real software: software systems are non-linear dynamic feedback environments, and static language models are fundamentally blind to compilers.

The Law of First-Step Plan Disintegration
In strictly typed languages like Rust or TypeScript, an elaborate ten-step architectural plan drafted in read-only isolation frequently disintegrates upon executing step one. An unexpected borrow checker violation or an esoteric generic constraint generates a fatal compiler diagnostic that the model could never foresee without running a build. The moment step one fails, the subsequent nine steps—crafted at great token expense—instantly become invalid noise cluttering the prompt context.

Language models cannot simulate full compiler semantics in their weights. Forcing an agent to draft comprehensive plans in an empirical vacuum slows down development velocity while generating an illusion of control.

Diminishing Returns: Why BYF Eliminated Plan Mode in ADR 0008
#

In the early architectural iterations of the open-source BYF engine, the team implemented a faithful replica of Claude Code’s Plan Mode. By ADR 0008, however, the team took a calculated decision: rip Plan Mode completely out of the core state machine.

The rationale was anchored in compounding runtime complexity and sharply diminishing returns:

1. Chronic Context Token Bleed
#

Sustaining Plan Mode imposed a persistent tax on every single conversational turn:

  • Schema definitions for EnterPlanMode and ExitPlanMode consumed roughly 1,425 tokens per turn, serialized into the prompt on every iteration.
  • A periodic PlanModeInjector injected repetitive system reminders (“You are currently in Plan Mode; do not modify files”) into history buffers.
  • The generated plan artifacts themselves occupied 2k to 5k tokens of high-priority context window.

2. Architectural Sprawl and State Contamination
#

Plan Mode was never a cleanly isolated feature; it invaded every layer of the system:

  • The CLI/TUI layer required dedicated /plan handlers, keybinding monitors, plan-card widgets, and status-bar badges.
  • The core orchestrator had to manage dual-state migrations, reentrancy guards, and complex transition rollbacks.
  • The implementation touched over 70 source files, driving up test maintenance overhead.

3. Degradation of the Barrier into Rubber-Stamping
#

Much like approval fatigue in security checkpoints, when an agent presents a 100-line markdown plan full of abstract prose, human developers rarely audit every line. They scan the headers and hit Enter. The rigorous barrier quickly degrades into empty ritual.

BYF concluded that an agent should interleave exploration and mutation in a continuous workflow, avoiding artificial lock-in to synthetic binary states. Developers can express “inspect the code and tell me your thoughts before writing” through plain language, achieving the same planning benefits without carrying the weight of an embedded state machine.

Practical Scoping: When to Plan and When to Act
#

Critiquing dogma does not mean rejecting planning. In production engineering, applying hard state boundaries is a question of task uncertainty versus blast radius:

Task ProfileCollaboration StanceEnforcement MechanismTrade-Off Analysis
Deterministic Local Fixes
(Single unit test fix, field addition, rename)
Continuous Interleaving (No Plan Mode)Direct execution with rapid test feedbackAvoids token waste and transition friction
Cross-Module Refactoring
(State management migration, ORM refactor)
Hard Barrier Planning (Plan Mode)Restrict write tools; mandate boundary blueprintMaximizes tree pruning; prevents dirty state spread
Unfamiliar Codebase Discovery
(Investigating foreign repos, auditing dependencies)
Exploratory Read-OnlyMount read-only toolset exclusivelyPrevents accidental modification during reconnaissance

Conclusion: Mechanical Splints on Stochastic Engines
#

Plan Mode is a mechanical splint bolted onto a stochastic system to curb its volatility.

By constricting degrees of freedom, it suppresses impulsive mutations driven by action myopia. Through an external FSM and human barrier synchronization, it truncates disastrous decision branches at trivial textual costs.

Yet sound engineering demands seeing the boundary: a splint immobilizes a fracture, but it cannot impart strength to the underlying bone. The moment a static plan loses contact with dynamic compiler diagnostics, it encounters the hard ceiling of diminishing returns. Knowing where to impose hard friction and where to enable fluid verification remains the true dividing line in building dependable AI developer tooling.

 Author
Author
ByF (BaiFan)
ByF,即 BaiFan(白帆)。系统后端工程师,专注 AI 底层原理与智能体架构。主站 baifan.site。
Claude Code Source Code Deconstruction - This article is part of a series.
Part : This Article