Skip to content

fix(cline): enforce plan hardening before presentation - #269

Merged
slowdini merged 1 commit into
devfrom
fix/cline-plan-gate-timing
Aug 8, 2026
Merged

fix(cline): enforce plan hardening before presentation#269
slowdini merged 1 commit into
devfrom
fix/cline-plan-gate-timing

Conversation

@slowdini

@slowdini slowdini commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Problem

First live test of the Cline plugin: the gate rejected an un-hardened plan after the plan had been presented and approved — when the agent called switch_to_act_mode to move into act mode. The intent is for hardening-plans to run over the plan before it's presented to the user.

Root cause

The plugin was modeled on Claude Code's ExitPlanMode, where the plan text rides inside the tool call, so a PreToolUse deny lands before the user ever sees the plan. Cline CLI works differently — its own plan-mode system prompt and the switch_to_act_mode tool description mandate the sequence: present the plan as a free-form message → end the turn → user approves in a follow-up message → only then call switch_to_act_mode. The hook was anchored to that last step, which is by design one approval late.

I also verified the full plugin hook surface (installed CLI 3.0.51 agent runtime + @cline/shared AgentRuntimeHooks agree): beforeRun, afterRun, beforeModel, afterModel, beforeTool, afterTool, onEvent. Plan presentation is streamed assistant text — no hook fires before or at presentation, so no re-timing of a single hook can fix this; the enforcement layers had to move.

Solution

Two-layer gate:

  1. Pre-presentation — rule: a new slow-powers/plan-presentation rule (registerRule) tells plan-mode agents to run hardening-plans on a draft before presenting it. A rule is the only mechanism that reaches the agent ahead of presentation.
  2. Pre-execution — hook as backstop: beforeTool on switch_to_act_mode gains the already-hardened short-circuit (parity with hooks/exit-plan-mode, issue Claude hook causes issues if hardening-plans is invoked autonomously #153): it scans snapshot.messages for a skills tool call naming hardening-plans. When the rule was followed, approval → switch passes with zero friction; when it wasn't, execution is blocked and the agent is instructed to harden, re-present the hardened plan, and retry. Detection matches the tool-input shape only (never prose), so the hook's own skip reason in the transcript cannot false-positive. The skip-once marker remains the fail-open floor — never hard-lock.
  3. Skip reason and plugin comments reworded: the hook gates execution, not presentation.

Testing

  • Harness tested: Cline. Unit tests drive the real plugin module — 5 new tests (rule registration, short-circuit for bare and namespaced skill names, full skip → harden → pass flow, and two false-positive guards). bun test: 167 pass / 0 fail; typecheck and biome clean.
  • Not a skill-prose change — deterministic harness wiring covered by unit tests, so no skill eval (stating the skip explicitly, per AGENTS.md).
  • Remaining manual check (unchanged from before): interactive cline -i plan-mode confirmation, since switch_to_act_mode isn't exposed in headless sessions.

No associated issue.

First live test of the Cline plugin showed the plan gate rejecting an un-hardened plan only after the plan had been presented and approved: in Cline, switch_to_act_mode is called post-approval by design (present plan -> end turn -> user approves -> switch), unlike Claude Code where the plan text rides inside ExitPlanMode. There is no Cline hook moment before plan presentation (verified against CLI 3.0.51's agent runtime and @cline/shared AgentRuntimeHooks), so the gate is now two-layer:

- a new slow-powers/plan-presentation rule (registerRule) tells plan-mode agents to run hardening-plans before presenting a plan - the only mechanism that reaches the agent pre-presentation;
- the beforeTool hook on switch_to_act_mode becomes the pre-execution backstop: an already-hardened transcript short-circuit (parity with hooks/exit-plan-mode, issue #153) lets a hardened plan through with no beat, else skip-once instructs the agent to harden, re-present, and retry. Detection matches the skills tool-input shape only, so the hook's own skip reason cannot false-positive;
- skip reason and plugin comments reworded: the hook gates execution, not presentation.

Tested on the Cline harness: unit tests drive the real plugin module (5 new tests; bun test 167 pass / 0 fail). Interactive TUI confirmation of the gate remains a manual check (switch_to_act_mode is not exposed headlessly).
@slowdini
slowdini merged commit 11d42d7 into dev Aug 8, 2026
1 check passed
@slowdini
slowdini deleted the fix/cline-plan-gate-timing branch August 8, 2026 04:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant