mcp: elicitation-gate worktrees remove force=true on a dirty or locked tree #168

Closed
opened 2026-07-16 21:10:53 +00:00 by hexajon · 0 comments
hexajon commented 2026-07-16 21:10:53 +00:00 (Migrated from codeberg.org)

The README's clobber section promises "Force exists, but you type it" - true for the CLI, not over MCP: madt_worktrees action=remove force=true discards a dirty or locked worktree with no consent step, and the non-force refusal text even points the agent at force=true (pinned in internal/mcp/tools_worktrees_test.go). The only guard today is the destructiveHint annotation, which is advisory to the client - a user who has allowlisted madt_* tools gets no ask at all.

Wire the same elicitation gate madt_delete uses:

  • MCP remove with force=true on a worktree that is dirty or locked elicits accept/decline before anything is deleted; decline returns a plain abort, not an error to route around.
  • Clients without elicitation support get a refusal naming the CLI command to run by hand - never a silent proceed.
  • A clean, unlocked worktree stays dialog-free (nothing to lose), and the CLI --force stays ungated (human-typed).
  • The sanctioned foreign-worktree abandon flow (internal/mcp/foreign_guard_chain_test.go) keeps working; it just gains the consent step when the tree is dirty.

This is the behavior change that makes the README's clobber claim true on the MCP surface, not just the CLI.

Acceptance:

  • forced MCP remove of a dirty worktree elicits; decline = no deletion, tree intact
  • non-elicitation client: refusal with CLI instructions, no deletion
  • clean, unlocked force remove unchanged
  • tool description, madt_help, and the safety docs state the gate
The README's clobber section promises "Force exists, but you type it" - true for the CLI, not over MCP: `madt_worktrees action=remove force=true` discards a dirty or locked worktree with no consent step, and the non-force refusal text even points the agent at `force=true` (pinned in `internal/mcp/tools_worktrees_test.go`). The only guard today is the `destructiveHint` annotation, which is advisory to the client - a user who has allowlisted `madt_*` tools gets no ask at all. Wire the same elicitation gate `madt_delete` uses: - MCP `remove` with `force=true` on a worktree that is dirty or locked elicits accept/decline before anything is deleted; decline returns a plain abort, not an error to route around. - Clients without elicitation support get a refusal naming the CLI command to run by hand - never a silent proceed. - A clean, unlocked worktree stays dialog-free (nothing to lose), and the CLI `--force` stays ungated (human-typed). - The sanctioned foreign-worktree abandon flow (`internal/mcp/foreign_guard_chain_test.go`) keeps working; it just gains the consent step when the tree is dirty. This is the behavior change that makes the README's clobber claim true on the MCP surface, not just the CLI. Acceptance: - [ ] forced MCP remove of a dirty worktree elicits; decline = no deletion, tree intact - [ ] non-elicitation client: refusal with CLI instructions, no deletion - [ ] clean, unlocked force remove unchanged - [ ] tool description, `madt_help`, and the safety docs state the gate
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#168
No description provided.