diff --git a/cli/smriti_cli/formatters.py b/cli/smriti_cli/formatters.py index cce1545..bf1b777 100644 --- a/cli/smriti_cli/formatters.py +++ b/cli/smriti_cli/formatters.py @@ -79,6 +79,10 @@ def _relative_time(iso_ts: str) -> str: then = datetime.fromisoformat(iso_ts.replace("Z", "+00:00")) except Exception: return iso_ts + if then.tzinfo is None: + then = then.replace(tzinfo=timezone.utc) + else: + then = then.astimezone(timezone.utc) now = datetime.now(timezone.utc) delta = now - then secs = int(delta.total_seconds()) diff --git a/cli/tests/test_state_multi_branch.py b/cli/tests/test_state_multi_branch.py index 511439d..88d7cb5 100644 --- a/cli/tests/test_state_multi_branch.py +++ b/cli/tests/test_state_multi_branch.py @@ -15,12 +15,13 @@ These tests cover the digestibility guarantees the build rests on: """ from __future__ import annotations -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone from smriti_cli import mcp_server from smriti_cli.formatters import ( _format_active_branches_section, _format_divergence_signal_section, + _relative_time, _task_section, _normalize_task_item, format_state_brief, @@ -74,6 +75,13 @@ def _base_commit(): # ── Formatter-level tests ──────────────────────────────────────────────────── +def test_relative_time_handles_aware_and_naive_iso_timestamps(): + two_hours_ago = datetime.now(timezone.utc) - timedelta(hours=2) + + assert _relative_time(two_hours_ago.isoformat()) == "2h ago" + assert _relative_time(two_hours_ago.replace(tzinfo=None).isoformat()) == "2h ago" + + def test_format_state_brief_no_space_state_matches_pre_build(): """With space_state=None, output must not contain any multi-branch sections. This is the regression guard for existing CLI callers."""