#866·ponytail

ponytail / audit / review: "Replacement: nothing" hides what a deletion leaves behind in the surviving code

Author: JochbartCreated Sep 13, 2026Updated Sep 13, 2026

ponytail's rules say "Deletion over addition", and ponytail-audit / ponytail-review phrase every delete: finding as "Replacement: nothing." That's true for the behaviour. It isn't true for the diff: removing a region leaves obligations in the code that stays.

Hit this while removing a dead UI variant (an unused layout branch of a list card component, plus a helper module only that branch used) in a React/TypeScript app. Each of these mattered, and none is covered by the skills:

  1. The rationale lived in the deleted branch. A long comment explaining a past accessibility fix sat on the branch being removed; the surviving branch only said "see the reasoning above". Plain deletion leaves a dangling pointer and loses the reason.
  2. Tests were pinned to the deleted variant. Two accessibility tests rendered only the dead variant. Deleting them along with it silently drops coverage of a variant that actually ships; they had to be retargeted, not removed.
  3. A ponytail: marker lived inside the removed helper, its ceiling meaningful only for the deleted path.
  4. "No other caller" had to include dynamic props (spread / conditionally set), and the prop itself could only go once a single value remained.

Adjacent, but not the same

  • #679 asks for a whole-tree caller check before delete:, including tests. That's point 4, and I agree with it. This issue is the other direction: what the surviving code points into the removed region, and what has to move with it.
  • #640 is about not deleting what nobody asked for. This is about deleting correctly when it was asked.

Suggested

In skills/ponytail/SKILL.md, next to "Deletion over addition" (L60), one line:

A deletion is done when nothing surviving points at the gap. Before removing a region, search the code that stays for references into it: call sites (including spread/dynamic props), comments that say "see above/below", tests that exercise only the removed path, ponytail: markers inside it. Move or retarget each.

In skills/ponytail-audit/SKILL.md (L19) and skills/ponytail-review/SKILL.md (L23), let Replacement name those obligations instead of implying "nothing" is always literal:

delete: dead code, unused flexibility, speculative feature. Replacement: nothing, or the obligations it leaves (e.g. "move rationale comment at L92 to L185; retarget 2 tests").

Checked against current main today: the rule at L60 and the delete: lines in audit (L19) and review (L23) are unchanged.

Happy to open the PR if useful.