From 04905313d97e674ca74eee9815574d70215f5c7f Mon Sep 17 00:00:00 2001 From: Jer Miller Date: Fri, 17 Jul 2026 22:02:54 -0600 Subject: [PATCH] refactor(home): device language in home glance copy Updates home health glance and needs-you degraded capture text to flat device-language owner copy. Internal identifiers, data keys, routes, schema, and CSS remain unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) --- solstone/apps/home/health_glance.py | 33 ++++++---------------- solstone/apps/home/needs_you.py | 40 +-------------------------- solstone/apps/home/static/home.js | 2 +- solstone/apps/home/tests/test_spa.py | 3 +- tests/test_home_health_glance.py | 34 +++++++++++++++++------ tests/test_home_needs_you.py | 23 +++++++-------- tests/test_post_action_terminology.py | 2 +- 7 files changed, 51 insertions(+), 86 deletions(-) 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", } -- 2.51.2