bug(prune): bare madtea prune deleted remote refs - bare run MUST be a pure dry run, guaranteed by test #133

Closed
opened 2026-07-15 23:14:04 +00:00 by hexajon · 0 comments
hexajon commented 2026-07-15 23:14:04 +00:00 (Migrated from codeberg.org)

A bare madtea prune (no flags) deleted remote refs without any confirmation (observed live, 2026-07-15). The declared contract says the opposite: internal/cmd/prune/prune.go:29 "By default, shows what would be deleted (dry run). Use --yes to actually delete", with --yes defaulting false (prune.go:42) and --dry-run accepted only for ergonomics because dry run is supposedly the default (prune.go:20).

So some code path mutates ref state during what is documented as a pure preview. Candidates to investigate:

  • the remote-orphan handling in internal/service/prune/run.go executing deletions (or git push --delete) on a path not gated by the confirm/yes flag;
  • a git fetch --prune (or equivalent) run during enumeration - that deletes local remote-TRACKING refs (origin/*) as a side effect, which still violates a pure dry run even though it does not touch the server;
  • MCP madt_prune and CLI sharing a service path where one surface's confirm semantics leak into the other's default.

Hard requirement

A bare madtea prune (and madt_prune without confirm=true) performs ZERO mutations: nothing deleted on the remote, no local branches deleted, no remote-tracking refs pruned, no ref state changed at all. Preview output only.

Asks

  1. Find and fix the mutating path; the fix must gate EVERY mutation (remote deletion, local branch deletion, tracking-ref pruning) behind the explicit confirm/--yes.
  2. Regression test that pins the contract: run bare prune against a hermetic repo+remote fixture with prunable state on all three axes, then assert the complete ref state (remote refs, local branches, remote-tracking refs) is byte-identical before and after. This test is the guarantee, not the help text.
  3. Audit for the same defect class on the other preview-by-default surfaces (anything with dry_run/confirm semantics) - a shared helper that mutates during enumeration would affect them all.

Acceptance

  • Bare prune provably mutates nothing (the fixture test above), on both CLI and MCP surfaces.
  • Explicit-confirm behavior unchanged.
  • Gate green.
A bare `madtea prune` (no flags) deleted remote refs without any confirmation (observed live, 2026-07-15). The declared contract says the opposite: internal/cmd/prune/prune.go:29 "By default, shows what would be deleted (dry run). Use --yes to actually delete", with `--yes` defaulting false (prune.go:42) and `--dry-run` accepted only for ergonomics because dry run is supposedly the default (prune.go:20). So some code path mutates ref state during what is documented as a pure preview. Candidates to investigate: - the remote-orphan handling in internal/service/prune/run.go executing deletions (or `git push --delete`) on a path not gated by the confirm/yes flag; - a `git fetch --prune` (or equivalent) run during enumeration - that deletes local remote-TRACKING refs (origin/*) as a side effect, which still violates a pure dry run even though it does not touch the server; - MCP madt_prune and CLI sharing a service path where one surface's confirm semantics leak into the other's default. ## Hard requirement A bare `madtea prune` (and madt_prune without confirm=true) performs ZERO mutations: nothing deleted on the remote, no local branches deleted, no remote-tracking refs pruned, no ref state changed at all. Preview output only. ## Asks 1. Find and fix the mutating path; the fix must gate EVERY mutation (remote deletion, local branch deletion, tracking-ref pruning) behind the explicit confirm/--yes. 2. Regression test that pins the contract: run bare prune against a hermetic repo+remote fixture with prunable state on all three axes, then assert the complete ref state (remote refs, local branches, remote-tracking refs) is byte-identical before and after. This test is the guarantee, not the help text. 3. Audit for the same defect class on the other preview-by-default surfaces (anything with dry_run/confirm semantics) - a shared helper that mutates during enumeration would affect them all. ## Acceptance - Bare prune provably mutates nothing (the fixture test above), on both CLI and MCP surfaces. - Explicit-confirm behavior unchanged. - Gate green.
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#133
No description provided.