Ash Resource Change behavior differs between REPL and GraphQL mutation

Right, so in this case to make it atomic:

defmodule SendPhaseComplete do
  use Ash.Resource.Change

  def change(changeset, _, context) do  
    Ash.Changeset.after_action(changeset, &PhaseComplete.send(&1, &2, context)
  end

  def atomic(changeset, opts, context) do
    {:ok, change(changeset, _, context)}
  end
end

Then you can refer to it as change SendPhaseComplete (giving it a better module name that makes sense for you.