Add a runs screen: a table, a run in full, and curves side by side

This commit is contained in:
2026-08-25 11:44:13 +02:00
parent 7e422c0047
commit d2951a325e
17 changed files with 1564 additions and 5 deletions
+49
View File
@@ -11,10 +11,12 @@ from fluksio.flow.dashboards import (
SettingDef,
WidgetDef,
default_dashboard,
results_dashboard,
)
from fluksio.flow.messages import DType, MessageSpec
from fluksio.flow.nodes import Node
from fluksio.flow.pipeline import Pipeline
from fluksio.flow.schemas import FlowDef, NodeDef
from fluksio.flow.state import MemoryState
from fluksio.flow.store import FlowStore, StaleVersion
@@ -444,3 +446,50 @@ def test_a_bound_setting_is_drawn_on_the_canvas(store: DashboardStore):
assert binding["requires"] == ["home.theme"]
assert not binding["provides"]
assert store.bindings_for("other") == []
def training_flow() -> FlowDef:
"""A batch flow shaped like an experiment: a curve and two results."""
return FlowDef(
name="study",
mode="batch",
outputs=["accuracy", "report"],
nodes=[
NodeDef(
id="fit",
provides=[
MessageSpec(name="loss", dtype=DType.FLOAT, stream=True),
MessageSpec(name="accuracy", dtype=DType.FLOAT),
MessageSpec(name="report", dtype=DType.RECORD),
MessageSpec(name="weights", dtype=DType.ARTIFACT),
],
)
],
)
def test_a_generated_dashboard_charts_the_curves_and_states_the_results():
"""The ports are the whole specification; nothing else is guessed."""
defn = results_dashboard(training_flow())
kinds = [(w.type, w.config.get("message")) for w in defn.widgets]
assert [w.type for w in defn.widgets] == ["chart", "stat", "notification"]
assert defn.widgets[0].config["series"][0]["message"] == "study.loss"
assert ("stat", "study.accuracy") in kinds
assert ("notification", "study.report") in kinds
def test_an_artifact_output_gets_no_widget():
"""A checkpoint has no single reading to draw."""
defn = results_dashboard(
training_flow().model_copy(update={"outputs": ["weights"]})
)
assert [w.type for w in defn.widgets] == ["chart"]
def test_a_flow_declaring_no_outputs_draws_no_stats():
"""Empty outputs means "everything", which is not a set to enumerate."""
defn = results_dashboard(training_flow().model_copy(update={"outputs": []}))
assert [w.type for w in defn.widgets] == ["chart"]