Live progress for the human report.
Progress is written to stderr so stdout remains safe for the final or machine-readable report. An interactive terminal gets a spinner, current mutant, counts, and ETA; pipes and CI logs get plain scrollback. Survivors, timeouts, and harness errors remain visible after the live display advances.
--verbose prints a line for every mutant and timing details for each phase. --quiet suppresses live progress entirely and takes precedence over --verbose.
Summary
Functions
Returns whether the reporter is using an animated ANSI status block.
Returns a specification to start this module under a supervisor.
Clears the current status block without stopping the reporter.
Returns whether persistent labels may use color.
Returns whether the default live reporter should draw its ANSI status block for the detected stderr terminal state.
Renders a verbose phase-completion event as a persistent status line.
Estimates remaining seconds from completed work, remaining work, and elapsed seconds.
Stops the status display and clears its terminal lines.
Milliseconds as one-decimal seconds (e.g. 450 → "0.5s", 3100 → "3.1s").
Seconds as Ns (under a minute) or Nm Ss.
Returns the persistent {label, color} for status, or nil when the status
only updates the counter.
Renders the macro-expansion poison fallback as a loud, persistent warning: names the
inline DSL macro(s) whose argument wouldn't compile with a mutation spliced in, and the
copy-paste route to pin the skip up front — :raw for a call, :skip for a head Mutare
analyzes structurally (Kernel.in), and a # mutare:ignore pointer for a head no route can
name (the classification Mutare.Poison.Hint uses).
Records a phase transition or verbose detail event.
Renders one compile-poison recovery round as a persistent status line: how many mutants were dropped and how many block macros were escalated (skipped wholesale), naming the escalated macros so the line explains why the compile is being retried.
Records a completed mutant result and updates the progress display.
Updates scanning progress with the processed file count, total file count, and number of mutants found.
Renders the app-build seed's outcome (Mutare.Sandbox.Seed.summary/0) as a persistent
status line, or nil for a :skipped seed (the broad-run default — no line even in
verbose). :seeded shows the reused vs recompiling beam counts; :partial adds how many
apps fell back (an umbrella per-app miss); :fallback names the otherwise-silent fall
back to a cold compile.
Starts the live reporter.
Records the mutant currently being tested.
Returns the status-block lines for state at monotonic time now_ms.
Returns the persistent {label, color} for status in verbose mode.
Types
@type phase_event() :: :scanning | :compiling | :baseline | :coverage_probe | {:running, non_neg_integer()} | {:compiled, non_neg_integer()} | {:baseline_done, non_neg_integer()} | {:coverage_done, map()} | {:run_config, map()} | {:poison_round, map()} | {:macro_poison, map()}
Functions
@spec animating?(GenServer.server()) :: boolean()
Returns whether the reporter is using an animated ANSI status block.
Plain reporters emit persistent lines but do not display the current-mutant activity line.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec clear(GenServer.server()) :: :ok
Clears the current status block without stopping the reporter.
This call is synchronous, so the terminal is clear before subsequent output.
@spec color_enabled?() :: boolean()
Returns whether persistent labels may use color.
Any non-empty NO_COLOR value disables color. This does not disable ANSI cursor
animation.
Returns whether the default live reporter should draw its ANSI status block for the detected stderr terminal state.
This is intentionally independent of IO.ANSI.enabled?/0: Elixir's flag is
initialized from stdout, but Mutare's live UI is written to stderr.
Renders a verbose phase-completion event as a persistent status line.
@spec eta_secs(non_neg_integer(), non_neg_integer(), non_neg_integer()) :: non_neg_integer() | nil
Estimates remaining seconds from completed work, remaining work, and elapsed seconds.
Returns nil until at least one item has completed and elapsed time is non-zero.
@spec finish(GenServer.server()) :: :ok
Stops the status display and clears its terminal lines.
@spec humanize_ms(non_neg_integer()) :: String.t()
Milliseconds as one-decimal seconds (e.g. 450 → "0.5s", 3100 → "3.1s").
@spec humanize_secs(non_neg_integer()) :: String.t()
Seconds as Ns (under a minute) or Nm Ss.
@spec leave_behind(Mutare.Result.status()) :: {String.t(), atom()} | nil
Returns the persistent {label, color} for status, or nil when the status
only updates the counter.
Renders the macro-expansion poison fallback as a loud, persistent warning: names the
inline DSL macro(s) whose argument wouldn't compile with a mutation spliced in, and the
copy-paste route to pin the skip up front — :raw for a call, :skip for a head Mutare
analyzes structurally (Kernel.in), and a # mutare:ignore pointer for a head no route can
name (the classification Mutare.Poison.Hint uses).
@spec phase(GenServer.server(), phase_event()) :: :ok
Records a phase transition or verbose detail event.
Phase transitions are :scanning, :compiling, :baseline,
:coverage_probe, and {:running, total}. Detail events are
{:compiled, ms}, {:baseline_done, ms}, {:coverage_done, summary}, and
{:run_config, cfg}. {:poison_round, info} (a compile-poison recovery round) and
{:macro_poison, info} (the macro-expansion fallback skipping an inline DSL macro)
each leave a permanent line in every mode, not just verbose.
Renders one compile-poison recovery round as a persistent status line: how many mutants were dropped and how many block macros were escalated (skipped wholesale), naming the escalated macros so the line explains why the compile is being retried.
@spec report(GenServer.server(), Mutare.Result.t()) :: :ok
Records a completed mutant result and updates the progress display.
@spec scanned(GenServer.server(), %{ done: non_neg_integer(), total: non_neg_integer(), found: non_neg_integer() }) :: :ok
Updates scanning progress with the processed file count, total file count, and number of mutants found.
Animated reporters redraw the status block. Plain reporters do not print a line for each update.
Renders the app-build seed's outcome (Mutare.Sandbox.Seed.summary/0) as a persistent
status line, or nil for a :skipped seed (the broad-run default — no line even in
verbose). :seeded shows the reused vs recompiling beam counts; :partial adds how many
apps fell back (an umbrella per-app miss); :fallback names the otherwise-silent fall
back to a cold compile.
@spec start_link(keyword()) :: GenServer.on_start()
Starts the live reporter.
Options:
:device— output device; defaults to:standard_error:ansi— enables or disables animation; by default it is enabled when stderr is a terminal:color— enables or disables colored persistent labels; by default it follows animation andNO_COLOR:width— terminal width; defaults to the detected width or 80:verbose— retains a line for every mutant and shows phase details; defaults tofalse
@spec started(GenServer.server(), Mutare.Site.t()) :: :ok
Records the mutant currently being tested.
Returns the status-block lines for state at monotonic time now_ms.
A running phase has an activity line and a counter. A pre-run phase has one line. An idle state has none. Cursor-control sequences are not included.
@spec verbose_leave(Mutare.Result.status()) :: {String.t(), atom()}
Returns the persistent {label, color} for status in verbose mode.
Every registered status has a verbose label. An unknown status raises.