diff --git a/plugins/host_agent/routes.py b/plugins/host_agent/routes.py
index 0eeec1f..e25c1da 100644
--- a/plugins/host_agent/routes.py
+++ b/plugins/host_agent/routes.py
@@ -548,13 +548,16 @@ async def host_panel(host_id: str):
hostlvl = latest.get(host.name, {})
ls = reg.last_seen_at if reg else None
- stale = bool(reg) and (
- ls is None or (datetime.now(timezone.utc) - ls).total_seconds() > _stale_after_seconds())
+ # "Deployed" is gated on the agent actually checking in (last_seen_at), NOT on
+ # the registration row — that row is minted before the playbook runs, so a
+ # failed provision would otherwise look deployed.
+ reporting = bool(reg) and ls is not None
+ stale = reporting and (datetime.now(timezone.utc) - ls).total_seconds() > _stale_after_seconds()
ansible_cfg = current_app.config.get("ANSIBLE", {})
return await render_template(
"panel.html",
- host=host, reg=reg, hostlvl=hostlvl, stale=stale, target=target,
+ host=host, reg=reg, hostlvl=hostlvl, reporting=reporting, stale=stale, target=target,
ansible_available=has_capability("ansible.run_playbook"),
managed_key_set=bool((ansible_cfg.get("ssh_public_key") or "").strip()),
)
diff --git a/plugins/host_agent/templates/panel.html b/plugins/host_agent/templates/panel.html
index 4e8cc5c..5279945 100644
--- a/plugins/host_agent/templates/panel.html
+++ b/plugins/host_agent/templates/panel.html
@@ -3,16 +3,18 @@
Agent
- {% if reg %}
+ {% if reporting %}
{{ 'stale' if stale else 'reporting' }}{% if reg.agent_version %} · v{{ reg.agent_version }}{% endif %}
- {% if reg.last_seen_at %} · last seen {{ reg.last_seen_at.strftime('%Y-%m-%d %H:%M') }}{% endif %}
+ · last seen {{ reg.last_seen_at.strftime('%Y-%m-%d %H:%M') }}
+ {% elif reg %}
+ pending — no check-in yet
{% endif %}
{% set cpu = hostlvl.get('cpu_pct') %}
{% set mem = hostlvl.get('mem_used_pct') %}
@@ -54,10 +56,21 @@
{% endif %}
{% else %}
- {# ── Not installed: provisioning path ── #}
+ {# ── Not reporting: pending (token minted, no check-in) or never installed ── #}
+ {% if reg %}
+
+ A token was minted for this host but no metrics have arrived yet — the
+ deploy may still be running, or it failed. Open the latest
+ Ansible run to check, then retry below. Live metrics appear here
+ once the agent checks in.
+
+ {% else %}
No agent installed. The agent reports CPU, memory, disk, network and more back to Steward.
+ {% endif %}
{% if session.user_role != 'admin' %}