StatifierUI.Kino (StatifierUI v0.11.0)

Copy Markdown View Source

The Livebook inspector: inspect/3 composes the four panes - configuration diagram, datamodel explorer, event injection, event log - over one shared StatifierUI.Trace.Subscriber, attached with catch-up (statifier ADR-0049), inside one Kino.Layout.

Compiled only when the optional :kino dependency is present (ADR-0004); a host without it gets a stub whose inspect/3 raises with instructions. Nothing else in this package touches Kino.

The scrubber (sui-3gg)

Four buttons above the diagram - First, Prev, Next, Live - move the diagram and the datamodel explorer from the live tip to any macrostep in the log and back. Selecting a macrostep draws the configuration that macrostep settled in, shows the datamodel as it stood at the end of that macrostep, opens its entry in the event log, and marks that entry - selected; the note above the diagram says which point is on screen. StatifierUI.Inspector decides all of it, so the whole behaviour is testable without Kino - this module only wires buttons to Updater.scrub/2.

Buttons rather than a click target on the log entry itself: the log pane is Kino.Markdown, which renders text and cannot carry a click handler back to the runtime. A directly clickable entry is the ADR-0008 renderer's to give, not Mermaid-and-Markdown's.

Lifecycle

Every process this module starts - the subscriber and the updater - goes through Kino.start_child/1, so re-evaluating the cell terminates them with it. The session notices the dead subscriber through its own monitor and drops it from its subscriber set: that is the clean detach, with nothing to unsubscribe by hand. The session itself is not owned here - it keeps running across cell re-evaluations, which is exactly what makes catch-up worth having.

Catch-up needs record: true

Start the session with record: true (and trace: true) for the inspector to reconstruct everything it missed. Without it the subscriber falls back to live delivery and the status header labels the panes Live-only - a partial stream is never presented as whole. Replay cost grows with run length (it re-runs the recording in the attaching process), so expect cell evaluation on a very long-lived session to take correspondingly longer.

Summary

Functions

Builds the inspector for session and returns the composed Kino.Layout for the cell to render.

Reopens a saved trace: the third leg of StatifierUI.Trace.Capture's record / save / reload.

Renders every bundle a palette discovery found, one panel after another, as a single Kino.Markdown widget.

Renders one fragment's fixture bundle as its "test this step" panel - its truth table plus its expectation results (sui-13q) - as a Kino.Markdown widget.

Renders fixtures' truth table - every expression evaluated across every dataset (ADR-0006) - as a Kino.Markdown widget.

Functions

inspect(session, fixtures \\ nil, opts \\ [])

@spec inspect(pid(), StatifierUI.Fixtures.t() | nil, keyword()) :: Kino.Layout.t()

Builds the inspector for session and returns the composed Kino.Layout for the cell to render.

fixtures is a StatifierUI.Fixtures.t/0 (or nil): it feeds the injection palette's per-event buttons. opts:

  • :source - the SCXML text, forwarded to the subscriber for the session.start manifest.
  • :capacity - the subscriber's buffer capacity (default 1000).

inspect_trace(trace, fixtures \\ nil, opts \\ [])

Reopens a saved trace: the third leg of StatifierUI.Trace.Capture's record / save / reload.

StatifierUI.Kino.inspect_trace("execution.jsonl")

trace is a file path (read through StatifierUI.Trace.Capture.load/1) or an already-loaded StatifierUI.Trace.Message.t/0 list. fixtures is accepted for symmetry with inspect/3 and is currently unused - the palette it feeds is an injection affordance, and there is nothing to inject into.

opts:

  • :machine - the compiled %Statifier.Machine{} to draw against. Optional: without it the machine is recompiled from the SCXML the trace carries in its own session.start message, which is what StatifierUI.Trace.Capture.record/3's :source option puts there. A trace captured without :source and reopened without :machine has no chart to draw and returns a Kino.Markdown saying so rather than a diagram it cannot draw.

Stepping it (sui-2uz)

The layout carries the same |< First / < Prev / Next > / Live scrubber inspect/3 has, plus a jump to select listing every macrostep by number and event, and a datamodel diff pane saying what the selected macrostep changed. A persisted stream has no tip that moves, so "Live" here means the end of the recording.

Stepping a recording asks the engine for nothing: every configuration shown was stamped by the engine into the file, and a trace read back through StatifierUI.Trace.Capture.load/1 got its contents from statifier ADR-0034 replay re-driving the core at capture time. The controls move a selection over messages already in hand.

What this is still not

There is no injection form. Injection drives a session, and a file has none. The fixtures argument stays accepted and unused for that reason.

palette_panel(discovery, opts \\ [])

Renders every bundle a palette discovery found, one panel after another, as a single Kino.Markdown widget.

discovery is what StatifierUI.Fixtures.Bundle.discover/2 or discover_dir/2 returned.

test_panel(bundle, opts \\ [])

@spec test_panel(
  StatifierUI.Fixtures.Bundle.t(),
  keyword()
) :: Kino.Markdown.t()

Renders one fragment's fixture bundle as its "test this step" panel - its truth table plus its expectation results (sui-13q) - as a Kino.Markdown widget.

Like truth_table/2, independent of inspect/3 and of any session: a bundle is a fact about one palette entry's examples, so this needs no running chart. opts go to StatifierUI.Fixtures.Bundle.Markdown.render/2, which forwards each one to the layer that owns it.

truth_table(fixtures, opts \\ [])

@spec truth_table(
  StatifierUI.Fixtures.t(),
  keyword()
) :: Kino.Markdown.t()

Renders fixtures' truth table - every expression evaluated across every dataset (ADR-0006) - as a Kino.Markdown widget.

Independent of inspect/3 and of any session: a truth table is a fact about expressions and datasets, so this needs no running chart and no Phoenix. opts are split by owner - :expressions, :datasets, :functions, and :providers go to StatifierUI.TruthTable.build/2, and the rest to StatifierUI.TruthTable.Markdown.render/2.