Epic: strict-omission destruction model - no madtea surface carries a work-destroying override #206

Closed
opened 2026-07-17 15:28:17 +00:00 by hexajon · 1 comment
hexajon commented 2026-07-17 15:28:17 +00:00 (Migrated from codeberg.org)

Safe by design, not by hoping an agent's incantations stay on the blessed path.

Auditing the destructive-operation surfaces turned up three coexisting safety models, grown case by case with no ADR pinning any of them:

  1. Omission - branch delete: force-delete exists on NO madtea surface. MCP has no force param and the CLI refuses -D/--force-delete, pointing at raw git branch -D in the user's own shell. Hooks then steer agents off raw git. Two independent layers, neither depending on the other behaving.
  2. Machine-proof destruction - prune (content-verified squash-merge before a ref drops) and push --force (force-with-lease). Refs die, work provably does not.
  3. Consent-gated presence (#168, #2004) - worktree remove force= and madt_delete DO exist on the agent surface, guarded by an elicitation dialog.

Model 3 already leaked twice:

  • madt_delete's confirm gate is skipped entirely on a client without elicitation support ("zero regression" fallback) - and non-elicitation clients are exactly the ones without PreToolUse hooks, while madt_enable(domains=["destructive"]) is agent-callable. Net: zero-consent irreversible deletion on those clients.
  • The worktree force-remove refusal ends with the runnable bypass: "run it yourself in a terminal: madtea worktree remove X --force" - the same deny-message-recommends-the-escape flaw ADR 0009 removed the opt-out keys for. And it only ever renders on the unhooked clients where that command works.

Decision: model 1 is the house rule. A madtea surface (MCP tool or CLI command) never carries an operation that can destroy unrecoverable work or data. Destruction is offered only when madtea can machine-prove nothing is lost (model 2). Where a user genuinely needs the irreversible op, refusals name the tool the user already holds - raw git in their own shell, or the forge web UI - as guidance for the user, never as a runnable madtea flag an agent can grab.

Exit criterion: ADR 0029 accepted; no MCP tool or CLI command can discard uncommitted work or irreversibly delete forge data; every refusal message points users at non-madtea tools; the elicitation-as-destruction-guard pattern is retired.

Safe by design, not by hoping an agent's incantations stay on the blessed path. Auditing the destructive-operation surfaces turned up three coexisting safety models, grown case by case with no ADR pinning any of them: 1. Omission - branch delete: force-delete exists on NO madtea surface. MCP has no force param and the CLI refuses -D/--force-delete, pointing at raw `git branch -D` in the user's own shell. Hooks then steer agents off raw git. Two independent layers, neither depending on the other behaving. 2. Machine-proof destruction - prune (content-verified squash-merge before a ref drops) and push --force (force-with-lease). Refs die, work provably does not. 3. Consent-gated presence (#168, #2004) - worktree remove force= and madt_delete DO exist on the agent surface, guarded by an elicitation dialog. Model 3 already leaked twice: - madt_delete's confirm gate is skipped entirely on a client without elicitation support ("zero regression" fallback) - and non-elicitation clients are exactly the ones without PreToolUse hooks, while madt_enable(domains=["destructive"]) is agent-callable. Net: zero-consent irreversible deletion on those clients. - The worktree force-remove refusal ends with the runnable bypass: "run it yourself in a terminal: madtea worktree remove X --force" - the same deny-message-recommends-the-escape flaw ADR 0009 removed the opt-out keys for. And it only ever renders on the unhooked clients where that command works. Decision: model 1 is the house rule. A madtea surface (MCP tool or CLI command) never carries an operation that can destroy unrecoverable work or data. Destruction is offered only when madtea can machine-prove nothing is lost (model 2). Where a user genuinely needs the irreversible op, refusals name the tool the user already holds - raw git in their own shell, or the forge web UI - as guidance for the user, never as a runnable madtea flag an agent can grab. Exit criterion: ADR 0029 accepted; no MCP tool or CLI command can discard uncommitted work or irreversibly delete forge data; every refusal message points users at non-madtea tools; the elicitation-as-destruction-guard pattern is retired. <!-- madtea:section:deps-children --> - [ ] #207 - [ ] #208 - [ ] #209 <!-- /madtea:section:deps-children -->
hexajon commented 2026-07-17 18:44:01 +00:00 (Migrated from codeberg.org)

All three children merged and the exit criterion is met. ADR 0029 accepted (PR #211). Worktree force-discard removed from both surfaces (#208, PR #233). madt_delete tool + the destructive domain + all five CLI delete operations converted to omission/web-UI refusals (#209, PR #234). The elicitation-as-destruction-guard pattern is fully retired - with both consumers gone, the elicitation seam itself was removed. No MCP tool or CLI command can now discard uncommitted work or irreversibly delete forge data, and every refusal points at the user's own tools (raw git, forge web UI) rather than a runnable madtea flag. The recoverable-but-wrong-workflow tier that this audit surfaced as adjacent got its own record in ADR 0031 (#222).

All three children merged and the exit criterion is met. ADR 0029 accepted (PR #211). Worktree force-discard removed from both surfaces (#208, PR #233). madt_delete tool + the destructive domain + all five CLI delete operations converted to omission/web-UI refusals (#209, PR #234). The elicitation-as-destruction-guard pattern is fully retired - with both consumers gone, the elicitation seam itself was removed. No MCP tool or CLI command can now discard uncommitted work or irreversibly delete forge data, and every refusal points at the user's own tools (raw git, forge web UI) rather than a runnable madtea flag. The recoverable-but-wrong-workflow tier that this audit surfaced as adjacent got its own record in ADR 0031 (#222).
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#206
No description provided.