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
call uses 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 stage drop (Mutare.Ecto.StageDrop): the call collapses to its
changeset argument, in both spellings — a pipe stage reaches the plugin as the direct call it
is sugar for, and the report keeps the pipe the user wrote (cs |> validate_required(…) →
cs).
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.
Every pipeline stage the plugin mutates — the droppable validators/constraints and the Repo-time
hooks. The one list Mutare.Ecto.call_routes/0 registers :routing (through
Mutare.Ecto.Changeset.Routing), so a stage is routed exactly when it is mutated.
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.
@spec stages() :: [atom()]
Every pipeline stage the plugin mutates — the droppable validators/constraints and the Repo-time
hooks. The one list Mutare.Ecto.call_routes/0 registers :routing (through
Mutare.Ecto.Changeset.Routing), so a stage is routed exactly when it is mutated.