All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.2.1 - 2026-10-03
Changed
- Requires Mutare 0.5 (
{:mutare, "~> 0.5.0"}) andmutare_phoenix0.3.1.
0.2.0 - 2026-09-26
Changed
- Breaking: requires Mutare 0.4.1 and mutare_phoenix 0.3 (
{:mutare, "~> 0.4.1"},{:mutare_phoenix, "~> 0.3"}). Mutare 0.4.0 offers a pipe stage to a mutator as the direct call it is sugar for, and removed the pipe-mode API these families were built on; every family now produces throughmutate/1, reading the socket at argument 0 whichever way the call was written. - A removed pipe stage collapses to the socket piped into it.
s |> push_event("a", %{})ands |> attach_hook(:log, :handle_event, &h/3)are diffed againsts; a stage removed in the middle of a chain takes everything upstream of it along (s |> push_event("a", %{}) |> assign(:x, 1)showss |> push_event("a", %{})→s). Through 0.1.0 such a stage readpush_event("a", %{})→Elixir.Function.identity(). The:lv_nav,:lv_streamand:lv_replydiffs are unchanged: a mutant that keeps the piped socket is still reported at the stage alone. - The
:lv_send_updateimmediatereplacement is parenthesized where it stands in for ado:value ((send_update(Cart, id: 1)\n:erlang.make_ref())), so the patched source is the program the mutant ran.
Added
:lv_send_updatemutates a pipedsend_update/send_update_after(pid |> send_update(Cart, id: 1)→:ok). Such a call was left alone through 0.1.0, when its:ok/ref stand-in could not be delivered as a pipe stage; it is the same call as the direct spelling and now gets the sameremoveandimmediatemutants, diffed over the whole pipe.
0.1.0 - 2026-09-07
Initial release.
Added
Mutare.Phoenix.LiveView.Navigation(:lv_nav) — swapspush_navigate↔push_patchat the arity-2 form both share.Mutare.Phoenix.LiveView.Reply(:lv_reply) — drops a callback's optional trailing tuple element ({:reply, payload, socket}→{:noreply, socket},{:ok, socket, opts}→{:ok, socket}), gated on the enclosing module'sPhoenix.LiveView/Phoenix.LiveComponentbehaviour.Mutare.Phoenix.LiveView.Stream(:lv_stream) — swapsstream_insert↔stream_deleteat the arity-3 form both share (swap); swapsat: 0 ↔ at: -1onstream_insert/4(at— prepend vs append; the covering rewrite supersedes core's integer leaves there via overlap pruning); drops thelimit:entry ofstream/4/stream_insert/4(limit). Droppingreset: trueis omitted because it is equivalent to core's boolean flip.Mutare.Phoenix.LiveView.Event(:lv_event) — removespush_event/3,4, collapsing to the socket (orFunction.identity()when piped, through 0.1.0).Mutare.Phoenix.LiveView.SendUpdate(:lv_send_update) — removessend_update/2,3/send_update_after/3,4, collapsing to a faithful stand-in (:ok/ a freshmake_ref()for_after's timer ref) (remove); and turnssend_update_after/3,4into an immediatesend_updatethat still yields a ref (immediate— deletes the delay). The delay argument is a marked:timeoutposition, so core's literal families skip it.Mutare.Phoenix.LiveView.Hook(:lv_hook) — removesattach_hook/4(attach— the hook never runs) anddetach_hook/3(detach— the hook keeps running), collapsing to the socket. Hook name and stage atoms are routed:raw, so no core family mutates them.- Registers the LiveView compile-time DSL (
live/live_session,on_mount,attr/slot/embed_templates) as:skipthroughMutare.CallRouting, so declarations that run once as mutant 0 are left unmutated. Mutare.Phoenix.LiveView.all/0for splicing the six families into a:mutatorslist, composing withMutare.Phoenix.all/0.