diff --git a/solstone/apps/home/health_glance.py b/solstone/apps/home/health_glance.py
index 5ff76d238..c98272597 100644
--- a/solstone/apps/home/health_glance.py
+++ b/solstone/apps/home/health_glance.py
@@ -75,7 +75,7 @@ def build_health_glance(
return {
"verdict": "ok",
"severity": "green",
- "headline": "no observers yet",
+ "headline": "no devices are running sol yet. set one up to start your journal.",
"last_observation": None,
"cta": {"text": "set one up →", "href": "/app/observer/"},
"issues": [],
@@ -83,7 +83,7 @@ def build_health_glance(
return {
"verdict": "unavailable",
"severity": "amber",
- "headline": "observer status unavailable",
+ "headline": "i don't know the status of your devices right now.",
"last_observation": None,
"cta": None,
"issues": [],
@@ -105,22 +105,20 @@ def _build_capture_issue(capture_health: Any) -> dict | None:
if status == "degraded":
text = format_degraded_capture_line(capture_health)
if not text:
- text = "an observer isn't reaching your journal"
+ text = "one of your devices isn't reaching your journal."
return {"text": text, "severity": "red", "href": "/app/health"}
if status == "offline":
return {
- "text": "no observer is reaching your journal",
+ "text": "nothing is reaching your journal.",
"severity": "red",
"href": "/app/health",
}
if status == "stale":
- name = _first_stale_observer_name(capture_health.get("observers"))
- text = (
- f"{name} hasn't reported recently"
- if name
- else "an observer hasn't reported recently"
- )
- return {"text": text, "severity": "amber", "href": "/app/health"}
+ return {
+ "text": "one of your devices hasn't reached your journal recently.",
+ "severity": "amber",
+ "href": "/app/health",
+ }
return None
@@ -144,19 +142,6 @@ def _pipeline_href(suggested_action: Any) -> str:
return _HEALTH_DETAIL_HREF
-def _first_stale_observer_name(observers: Any) -> str | None:
- if not isinstance(observers, list):
- return None
- for observer in observers:
- if not isinstance(observer, dict) or observer.get("status") != "stale":
- continue
- name = observer.get("name")
- if isinstance(name, str) and name.strip():
- return name.strip()
- return None
- return None
-
-
def _observer_state(capture_health: Any) -> str:
if not isinstance(capture_health, dict):
return "unknown"
diff --git a/solstone/apps/home/needs_you.py b/solstone/apps/home/needs_you.py
index db4a0e457..784c29839 100644
--- a/solstone/apps/home/needs_you.py
+++ b/solstone/apps/home/needs_you.py
@@ -4,12 +4,10 @@
from __future__ import annotations
import logging
-import math
from dataclasses import dataclass
from typing import Any, Literal
from solstone.convey.chat_sources import parse_sol_sources
-from solstone.convey.utils import format_month_day
logger = logging.getLogger(__name__)
@@ -104,14 +102,6 @@ def needs_dedup_key(item: Any) -> str:
return "text:" + _normalize_item(_need_display_text(item))
-def _finite_number(value: Any) -> bool:
- return (
- isinstance(value, (int, float))
- and not isinstance(value, bool)
- and math.isfinite(value)
- )
-
-
def format_degraded_capture_line(capture_health: dict) -> str | None:
"""Single combined owner line for a degraded capture state, else None.
@@ -123,35 +113,7 @@ def format_degraded_capture_line(capture_health: dict) -> str | None:
or capture_health.get("status") != "degraded"
):
return None
- observers = capture_health.get("observers")
- candidates = (
- [
- o
- for o in observers
- if isinstance(o, dict)
- and o.get("status") == "degraded"
- and isinstance(o.get("ingest_rejection"), dict)
- ]
- if isinstance(observers, list)
- else []
- )
- if not candidates:
- return "an observer isn't reaching your journal"
- first = candidates[0]
- more = len(candidates) - 1
- suffix = f", and {more} more" if more > 0 else ""
- name = first.get("name")
- name = name.strip() if isinstance(name, str) else ""
- if not name:
- return "an observer isn't reaching your journal" + suffix
- rejection = first["ingest_rejection"]
- count = rejection.get("active_count")
- first_ts = rejection.get("first_ts")
- if _finite_number(count) and _finite_number(first_ts):
- clause = f" — {int(count)} rejected since {format_month_day(first_ts)}"
- else:
- clause = ""
- return f"{name} isn't reaching your journal{clause}{suffix}"
+ return "one of your devices isn't reaching your journal."
def _classify_safely(
diff --git a/solstone/apps/home/static/home.js b/solstone/apps/home/static/home.js
index c2805c891..7b4ce3d84 100644
--- a/solstone/apps/home/static/home.js
+++ b/solstone/apps/home/static/home.js
@@ -238,7 +238,7 @@
});
} else {
if (g.last_observation) {
- html += '
last observation ' + esc(g.last_observation) + '
';
+ html += 'last reached your journal ' + esc(g.last_observation) + '
';
}
if (g.cta) {
html += ''
diff --git a/solstone/apps/home/tests/test_spa.py b/solstone/apps/home/tests/test_spa.py
index 986d619ab..c7eece0d4 100644
--- a/solstone/apps/home/tests/test_spa.py
+++ b/solstone/apps/home/tests/test_spa.py
@@ -162,7 +162,7 @@ const pulsePayload = {
verdict: 'ok',
severity: 'green',
headline: "everything's working",
- last_observation: null,
+ last_observation: '5m ago',
cta: null,
issues: [],
},
@@ -386,6 +386,7 @@ function makeContext(apiJson) {
await flush();
assert(success.apiCalls.filter(url => url === '/app/home/api/pulse').length === 1, 'pulse should fetch once');
assert(success.surface.innerHTML.includes('pulse-vitals'), 'pulse render did not populate vitals');
+ assert(success.surface.innerHTML.includes('last reached your journal 5m ago'), 'health glance last observation label missing');
assert(success.surface.innerHTML.includes('pulse-narrative'), 'pulse render did not populate narrative');
assert(!success.surface.innerHTML.includes('data-home-surface="connections"'), 'missing connections payload should not render connections');
diff --git a/tests/test_home_health_glance.py b/tests/test_home_health_glance.py
index bbda4b6ee..53847fe98 100644
--- a/tests/test_home_health_glance.py
+++ b/tests/test_home_health_glance.py
@@ -11,7 +11,7 @@ import pytest
from solstone.apps.home.health_glance import build_health_glance
BANNED_RE = re.compile(
- r"\b(watch|capture|record|monitor|track|collect)\b",
+ r"\b(watch|capture|record|monitor|track|collect|observer|observation)\b",
re.IGNORECASE,
)
EXTENDED_BANNED_RE = re.compile(
@@ -64,7 +64,10 @@ def test_degraded_capture_returns_red_attention_issue():
assert len(result["issues"]) == 1
assert result["issues"][0]["severity"] == "red"
assert result["issues"][0]["href"] == "/app/health"
- assert "fedora" in result["issues"][0]["text"]
+ assert (
+ result["issues"][0]["text"]
+ == "one of your devices isn't reaching your journal."
+ )
assert result["headline"] != "everything's working"
@@ -74,7 +77,10 @@ def test_degraded_capture_collapses_multiple_observers_to_one_issue():
)
assert len(result["issues"]) == 1
- assert "and 2 more" in result["issues"][0]["text"]
+ assert (
+ result["issues"][0]["text"]
+ == "one of your devices isn't reaching your journal."
+ )
def test_degraded_capture_and_pipeline_warning_returns_two_issues_red_verdict():
@@ -117,17 +123,24 @@ def test_pipeline_warning_without_headline_uses_fallback_text():
@pytest.mark.parametrize(
- "capture_health",
+ ("capture_health", "issue_text"),
[
- {"status": "offline", "observers": []},
- {"status": "stale", "observers": [{"name": "fedora", "status": "stale"}]},
+ (
+ {"status": "offline", "observers": []},
+ "nothing is reaching your journal.",
+ ),
+ (
+ {"status": "stale", "observers": [{"name": "fedora", "status": "stale"}]},
+ "one of your devices hasn't reached your journal recently.",
+ ),
],
)
-def test_offline_and_stale_capture_do_not_return_ok(capture_health):
+def test_offline_and_stale_capture_do_not_return_ok(capture_health, issue_text):
result = build_health_glance(capture_health, None, None)
assert result["verdict"] != "ok"
assert result["headline"] != "everything's working"
+ assert result["issues"][0]["text"] == issue_text
def test_active_capture_without_pipeline_returns_ok_with_last_observation():
@@ -147,7 +160,10 @@ def test_no_observers_returns_ok_with_setup_cta():
assert result["verdict"] == "ok"
assert result["severity"] == "green"
- assert result["headline"] == "no observers yet"
+ assert (
+ result["headline"]
+ == "no devices are running sol yet. set one up to start your journal."
+ )
assert result["last_observation"] is None
assert result["cta"] == {"text": "set one up →", "href": "/app/observer/"}
@@ -157,7 +173,7 @@ def test_unknown_observer_state_returns_unavailable():
assert result["verdict"] == "unavailable"
assert result["severity"] == "amber"
- assert result["headline"] == "observer status unavailable"
+ assert result["headline"] == "i don't know the status of your devices right now."
assert result["verdict"] != "ok"
assert result["headline"] != "everything's working"
diff --git a/tests/test_home_needs_you.py b/tests/test_home_needs_you.py
index ebf198f2f..bff12966d 100644
--- a/tests/test_home_needs_you.py
+++ b/tests/test_home_needs_you.py
@@ -102,16 +102,17 @@ def test_needs_dedup_key_legacy_strings_normalize_text():
)
-def test_format_degraded_capture_line_single_named_full():
+def test_format_degraded_capture_line_returns_flat_sentence():
line = format_degraded_capture_line(_degraded_capture())
- assert line == "fedora isn't reaching your journal — 79 rejected since jun 22"
+ assert line == "one of your devices isn't reaching your journal."
assert "segment" not in line
assert "screen.jsonl" not in line
assert "/tmp/private" not in line
+ assert "fedora" not in line
-def test_format_degraded_capture_line_multiple_combines_first_and_count():
+def test_format_degraded_capture_line_multiple_stays_flat():
capture = _degraded_capture()
capture["observers"].append(
{
@@ -129,32 +130,32 @@ def test_format_degraded_capture_line_multiple_combines_first_and_count():
}
)
- assert (
- format_degraded_capture_line(capture)
- == "fedora isn't reaching your journal — 79 rejected since jun 22, and 1 more"
+ assert format_degraded_capture_line(capture) == (
+ "one of your devices isn't reaching your journal."
)
-def test_format_degraded_capture_line_named_without_required_count_or_date():
+def test_format_degraded_capture_line_ignores_missing_count_or_date():
missing_ts = _degraded_capture()
del missing_ts["observers"][0]["ingest_rejection"]["first_ts"]
assert (
- format_degraded_capture_line(missing_ts) == "fedora isn't reaching your journal"
+ format_degraded_capture_line(missing_ts)
+ == "one of your devices isn't reaching your journal."
)
assert (
format_degraded_capture_line(_degraded_capture(active_count=None))
- == "fedora isn't reaching your journal"
+ == "one of your devices isn't reaching your journal."
)
def test_format_degraded_capture_line_fallbacks_and_non_degraded():
assert (
format_degraded_capture_line(_degraded_capture(include_rejection=False))
- == "an observer isn't reaching your journal"
+ == "one of your devices isn't reaching your journal."
)
assert (
format_degraded_capture_line({"status": "degraded", "observers": []})
- == "an observer isn't reaching your journal"
+ == "one of your devices isn't reaching your journal."
)
assert format_degraded_capture_line({"status": "active", "observers": []}) is None
diff --git a/tests/test_post_action_terminology.py b/tests/test_post_action_terminology.py
index b4e253d56..df09d31ce 100644
--- a/tests/test_post_action_terminology.py
+++ b/tests/test_post_action_terminology.py
@@ -42,7 +42,7 @@ def _minimal_home_context() -> dict:
"cta": None,
"issues": [
{
- "text": "no observer is reaching your journal",
+ "text": "nothing is reaching your journal.",
"severity": "red",
"href": "/app/health",
}