{# Operator dashboard metrics (issue #13; summary cards + mini-bars #91). Rendered standalone on the htmx 15s poll (HX-Request) and included by dashboard.html for the full page. Pure read-only render over a SystemStats snapshot — no aggregation here; that all lives in stats_query.collect_stats(). ALL markup stays in this fragment so the innerHTML poll swaps identical structure (initial render == refresh). #}
Snapshot at . Throughput window since .
{# The invalid-?since= notice is rendered by dashboard.html OUTSIDE the "Show run details" disclosure (issue #117 Phase C): an error the operator must see is never hidden, and it must not vanish on the 15s poll (the poll drops the bad value and re-takes the default, so the fragment never carries the notice). #} {# Curated hardware strip (W3): warnings + neutral GPU activity, refreshed on the same 15s poll as the run figures below. The fuller live view is one click away. #} {% include "fragments/resource_strip.html" %} {# Summary-first stat cards (issue #91). The exact figures the tables below detail, surfaced at a glance; each card keeps its unit as text. The review backlog is deliberately NOT here (issue #117 Phase C): it is promoted to the static "Continue review (N)" task card on the full page. A second copy inside this 15s-polled fragment would refresh independently and could show a count that contradicts the static card, so this fragment carries throughput and stage detail only. #}| Status | Runs |
|---|---|
| {{ humanize_status(status.value) }} | {{ stats.status_counts.get(status.value, 0) }} |
| Stage | Avg duration | Finished attempts |
|---|---|---|
| {{ humanize_stage(d.stage) }} | {{ "%.2f"|format(d.avg_seconds) }}s | {{ d.attempt_count }} |
No finished stage attempts yet.
{% endif %}| Stage | Failed attempts |
|---|---|
| {{ humanize_stage(f.stage) }} | {{ f.attempt_count }} |
No stage failures recorded.
{% endif %}