DSH plugin plan mode: plan/mode, pending and exit_plan_mode
DSH plugin plan mode is not a permission switch; it is a per-agent collaboration state written to the log. While active it does one thing: adds a deployment-owned plan:policy section to every model request. Real restrictions come from sandbox and approval, neither of which reads plan state. That boundary explains two behaviors that look like bugs: the current turn does not change right after toggling (the selection waits for the next accepted in-turn pre-step), and exit_plan_mode stays in the tool catalog when inactive (so entering and leaving only change the prompt section).
DSH plugin plan state: the plan/mode event and replay
Bottom line: the mode is a whole-value log event, persisted and replayable, and never part of the model transcript.
- Payload:
plan/modeis{ active: boolean }, whole-value replaced. - Replay: resume, fork and compaction all restore logged state and pending selections from the log.
- Fold unit: the optional
planunit folds committed mode, command settlements and the last request-header-recorded mode. - Read entry:
ctx.planModeexposesstateOf(); a missing registry,plankey orturnBoundarykey fails on first access. - Client view: only
{ active, pending }, no internal folding details.
DSH plugin pending selections: why toggles are not immediate
Bottom line: every session event lies within a turn, so a selection must wait for an accepted in-turn pre-step before the request is derived.
- Pending rule: a user selection stays pending until the next accepted in-turn pre-step appends it, regardless of which turn that pre-step belongs to.
- No forced continuation: a selection does not make the agent continue, so one made after a turn's last accepted pre-step is appended in a later turn.
setoutcomes:committed(logged now),queued(awaiting append),cancelled(an opposite pending selection was cleared) ornoop.getsemantics: logged state plus an optional pending state; assembling the current step uses the logged one.- Known limitation: a selection made after the turn's last pre-step exists only in-process and is lost if the process exits first.
DSH plugin append point: agent/pre-step and the one-time notice
Bottom line: the only append point is a prepend-registered pre-step listener, and append failure must not block the turn.
- Observation scope: every candidate request step, including turn 1 step 1 and request resume retries.
- Decision order: call downstream listeners first, appending only after they accept the step.
- Prompt-stage limit: prompt admission happens before the turn opens, so a selection there is applied by the first accepted pre-step of the turn it opens.
- Failure handling: append failures must not block the turn; the selection keeps waiting.
- Model notification: appending records a plugin-origin
user/messageonly when the last request header described a different state, so the model is notified exactly when context changes and never twice.
DSH plugin config and exit: section and exit_plan_mode
Bottom line: guidance text is deployment-owned and validated at load; the exit tool is always registered but only executes in plan mode.
- Config shape:
PlanModeConfig { section: string }; missing, blank, non-string or unknown keys fail at load. - Rendering: while active, the exact section renders as
plan:policyat order 50; inactive contributes nothing. - Exit tool:
exit_plan_modestays registered outside plan mode and fails there; inside plan mode it requires a complete markdown plan starting with#. - Review flow: submitted through the user-questions seam; approval returns
{ approved: true }and records a silent pending exit. - Continue planning: a failed call carrying feedback, so the model revises and resubmits; a missing interaction channel or a service reload also fails the call rather than silently leaving.
/plan: bare/planselects plan mode,/plan offselects inactive and cancels a not-yet-visible pending entry, and/plan <message>selects the mode then submits the text through steer as a normal logged user message.
DSH plugin plan mode versus sandbox and approval
Bottom line: plan mode governs how the agent talks, sandbox and approval govern what it may do — none reads the others' state.
- Plan mode: soft guidance affecting only the prompt.
- Sandbox mode: enforces process and file constraints without reading plan state.
- Approval policy: decides whether an operation needs approval, also without plan state.
- Configure them separately: to make planning genuinely more conservative, tighten sandbox and approval too.
- Rule of thumb: if files still change in plan mode, the sandbox or approval is unconfigured — plan mode never enforced that.
DSH plugin plan mode troubleshooting
Bottom line: separate not applied, not exited and lost state.
- Toggled but unchanged — normal; wait for an accepted in-turn pre-step and check whether
setreturnedqueued. - Still running after a plan is submitted — approval is a pending exit; the rest of the batch still follows plan guidance.
- State lost — the selection happened after the last pre-step and the process exited, a known limitation.
- No
plan:policy— check the section config and whether the mode is actually active. - Expecting tool restrictions — plan mode does not restrict; check sandbox and approval.
- Repair status, stated honestly: event shape, pending rules, append point and exit flow follow the official Plan mode page and package README; confirm signatures and command behavior against its Cordis API and your version.
Sources: Plan mode, dsh-plan-mode README, System prompt.
FAQ
DSH plugin plan mode is soft guidance: while active, each model request carries deployment-owned plan guidance but tools are not restricted. Sandbox mode and approval policy enforce separately, and neither reads or writes plan state.
DSH plugin selections are pending inside a turn until the next accepted in-turn pre-step appends them before deriving the request. A selection made at prompt admission cannot append directly and is applied by the first accepted pre-step of the turn it opens.
The DSH plugin exit_plan_mode tool stays registered so the tool catalog never changes with the mode, but executing it outside plan mode fails. That keeps entering and leaving plan mode limited to the prompt section.
Approval records a silent pending exit that the next accepted in-turn pre-step appends, so DSH plugin plan guidance remains in force for the rest of the current tool batch. The tool result itself reports the transition.
Yes: that DSH plugin selection exists only in-process, and it is lost if the process exits before another accepted in-turn pre-step. Selections made between turns are appended immediately because no in-turn pre-step will run.
Related Terms
- plan/mode
- plan/mode is the plan mode session event carrying {active: boolean}, whole-value replaced and log-only. It is persisted and replayable but never enters the model transcript.— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/plan
- pending selection
- A pending selection is a recorded-but-not-yet-logged mode switch that waits for the next accepted in-turn pre-step to append it before deriving the request. Clients only see {active, pending}.— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/plan
- plan:policy
- plan:policy is the system prompt section injected while DSH plugin plan mode is active, containing the deployment-configured section text rendered at order 50. Inactive plan mode contributes no text.— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/plan
- exit_plan_mode
- exit_plan_mode is the stably registered exit tool: in plan mode it requires a complete markdown plan starting with a # heading and submits it for review, recording a silent pending exit on approval.— https://deepseek-harness.github.io/deepseek-harness/reference/subsystems/plan
Sources
- DeepSeek Harness docs — Plan mode (plan/mode, pending selections, config, exit tool and /plan)· deepseek-harness.github.io
- dsh-plan-mode package README (known limitations and deferred work)· deepseek-ai (GitHub)
- DeepSeek Harness docs — System prompt (plan:policy section and assembly order)· deepseek-harness.github.io