Drop a transparent step from a changeset pipeline — the changeset equivalent of removing a
guard. cs |> validate_required([:name]) → cs. A surviving mutant means no test
exercises the behaviour that step contributes. Matched by resolving the call to
Ecto.Changeset (direct, aliased, or the common import Ecto.Changeset), so the form the
source wrote doesn't matter.
Two families, dropped by the same machinery but kept apart because the thing being removed differs:
:validation_drop— a validator or constraint (validate_required,unique_constraint, …). Each returns the changeset unchanged on the happy path, so dropping it is always behaviour-preserving except for the rule it enforces. A survivor means the rule is untested.:hook_drop— a deferred Repo-time hook (prepare_changes,optimistic_lock). These are not validators: they register code/locks the Repo runs atinsert/updatetime (a counter bump, a derived column, a stale-version guard). Dropping one is still compile-safe and changeset-shape-preserving, but the gap it surfaces is "this side effect / concurrency guard is never asserted", a different question — so it gets its own family.
Delivery is the shared pipe-aware stage drop (Mutare.Ecto.StageDrop): piped, the stage becomes
Function.identity/1; written directly, the call collapses to its changeset argument.
Summary
Functions
Changeset-step drop mutations for an Ecto.Changeset call as tags, or [].
A validator/constraint drops under :validation_drop; a Repo-time hook under :hook_drop.
Functions
@spec mutations(Macro.t(), Mutare.Ecto.Context.t()) :: [Mutare.Ecto.Tag.t()]
Changeset-step drop mutations for an Ecto.Changeset call as tags, or [].
A validator/constraint drops under :validation_drop; a Repo-time hook under :hook_drop.