# SPDX-License-Identifier: AGPL-3.0-only # Copyright (c) 2026 sol pbc from __future__ import annotations import logging from datetime import datetime from pathlib import Path from zoneinfo import ZoneInfo from solstone.think.utils import get_owner_timezone, sunday_of_week def test_get_owner_timezone_uses_configured_zone(monkeypatch): monkeypatch.setattr( "solstone.think.utils.get_config", lambda: {"identity": {"timezone": "America/New_York"}}, ) tz = get_owner_timezone() assert tz == ZoneInfo("America/New_York") def test_get_owner_timezone_falls_back_to_host_zone(monkeypatch, caplog): class FixedDateTime(datetime): @classmethod def now(cls, tz=None): return cls(2026, 4, 20, 12, 0, tzinfo=ZoneInfo("UTC")) monkeypatch.setattr( "solstone.think.utils.get_config", lambda: {"identity": {"timezone": "Mars/Olympus"}}, ) monkeypatch.setattr("solstone.think.utils.datetime", FixedDateTime) with caplog.at_level(logging.WARNING): tz = get_owner_timezone() assert tz == ZoneInfo("UTC") assert "falling back to host timezone" in caplog.text def test_sunday_of_week_returns_most_recent_sunday(): tz = ZoneInfo("America/Denver") assert sunday_of_week(datetime(2026, 3, 8, 9, 0), tz) == "20260308" assert sunday_of_week(datetime(2026, 3, 10, 9, 0), tz) == "20260308" def _patch_weekly_runtime( monkeypatch, journal_path: Path, prompts: dict[str, dict], *, enabled_facets: dict[str, dict] | None = None, active_facets: set[str] | None = None, ) -> list[tuple[str, str, dict]]: captured: list[tuple[str, str, dict]] = [] monkeypatch.setattr( "solstone.think.thinking.get_owner_timezone", lambda: ZoneInfo("UTC") ) monkeypatch.setattr( "solstone.think.thinking.get_journal", lambda: str(journal_path) ) monkeypatch.setattr( "solstone.think.thinking.get_talent_configs", lambda schedule: prompts ) monkeypatch.setattr( "solstone.think.thinking.day_input_summary", lambda day: "summary" ) monkeypatch.setattr( "solstone.think.thinking.get_enabled_facets", lambda: enabled_facets or {} ) monkeypatch.setattr( "solstone.think.thinking.get_active_facets", lambda day: active_facets or set() ) monkeypatch.setattr("solstone.think.thinking._update_status", lambda **kwargs: None) monkeypatch.setattr("solstone.think.thinking.emit", lambda *args, **kwargs: None) monkeypatch.setattr( "solstone.think.thinking._jsonl_log", lambda *args, **kwargs: None ) monkeypatch.setattr( "solstone.think.thinking._log_skip", lambda *args, **kwargs: None ) def fake_request(prompt: str, name: str, config: dict) -> str: captured.append((prompt, name, config)) return f"use-{len(captured)}" monkeypatch.setattr( "solstone.think.thinking._dispatch_cortex_request", fake_request ) monkeypatch.setattr( "solstone.think.thinking._drain_priority_batch", lambda spawned, *_args: (len(spawned), 0, []), ) return captured def test_run_weekly_prompts_sets_weekly_reflection_output_override( tmp_path, monkeypatch ): from solstone.think.thinking import run_weekly_prompts captured = _patch_weekly_runtime( monkeypatch, tmp_path / "journal", {"weekly_reflection": {"type": "cogitate", "priority": 90}}, ) success, failed, failed_names = run_weekly_prompts( day="20260310", refresh=False, verbose=False, ) assert (success, failed, failed_names) == (1, 0, []) assert len(captured) == 1 _prompt, name, config = captured[0] assert name == "weekly_reflection" assert config["day"] == "20260308" assert config["output"] == "md" assert config["output_path"] == str( tmp_path / "journal" / "reflections" / "weekly" / "20260308.md" ) assert config["env"]["SOL_DAY"] == "20260308" assert config["schedule"] == "weekly" def test_run_weekly_prompts_sets_override_for_multifacet_weekly_reflection( tmp_path, monkeypatch ): from solstone.think.thinking import run_weekly_prompts captured = _patch_weekly_runtime( monkeypatch, tmp_path / "journal", { "weekly_reflection": { "type": "cogitate", "priority": 90, "multi_facet": True, } }, enabled_facets={"work": {"title": "Work"}}, active_facets={"work"}, ) success, failed, failed_names = run_weekly_prompts( day="20260310", refresh=False, verbose=False, ) assert (success, failed, failed_names) == (1, 0, []) assert len(captured) == 1 _prompt, name, config = captured[0] assert name == "weekly_reflection" assert config["facet"] == "work" assert config["day"] == "20260308" assert config["output"] == "md" assert config["output_path"] == str( tmp_path / "journal" / "reflections" / "weekly" / "20260308.md" ) assert config["env"]["SOL_DAY"] == "20260308" assert config["env"]["SOL_FACET"] == "work" def test_run_weekly_prompts_persists_cogitate_with_output(tmp_path, monkeypatch): from solstone.think.thinking import run_weekly_prompts captured = _patch_weekly_runtime( monkeypatch, tmp_path / "journal", {"exec": {"type": "cogitate", "priority": 50, "output": "md"}}, ) success, failed, failed_names = run_weekly_prompts( day="20260310", refresh=False, verbose=False, ) assert (success, failed, failed_names) == (1, 0, []) assert len(captured) == 1 _prompt, name, config = captured[0] assert name == "exec" assert config["output"] == "md" assert "refresh" not in config def test_run_weekly_prompts_refreshes_cogitate_with_output(tmp_path, monkeypatch): from solstone.think.thinking import run_weekly_prompts captured = _patch_weekly_runtime( monkeypatch, tmp_path / "journal", {"exec": {"type": "cogitate", "priority": 50, "output": "md"}}, ) success, failed, failed_names = run_weekly_prompts( day="20260310", refresh=True, verbose=False, ) assert (success, failed, failed_names) == (1, 0, []) assert len(captured) == 1 _prompt, name, config = captured[0] assert name == "exec" assert config["output"] == "md" assert config["refresh"] is True def test_run_weekly_prompts_compose_output_helper_with_reflection_override( tmp_path, monkeypatch ): from solstone.think.thinking import run_weekly_prompts captured = _patch_weekly_runtime( monkeypatch, tmp_path / "journal", { "weekly_reflection": { "type": "cogitate", "priority": 90, "output": "md", } }, ) success, failed, failed_names = run_weekly_prompts( day="20260310", refresh=False, verbose=False, ) assert (success, failed, failed_names) == (1, 0, []) assert len(captured) == 1 _prompt, name, config = captured[0] assert name == "weekly_reflection" assert config["output"] == "md" assert config["output_path"] == str( tmp_path / "journal" / "reflections" / "weekly" / "20260308.md" ) assert config["day"] == "20260308" assert config["env"]["SOL_DAY"] == "20260308" assert "refresh" not in config def test_run_weekly_prompts_refresh_survives_reflection_override(tmp_path, monkeypatch): from solstone.think.thinking import run_weekly_prompts captured = _patch_weekly_runtime( monkeypatch, tmp_path / "journal", { "weekly_reflection": { "type": "cogitate", "priority": 90, "output": "md", } }, ) success, failed, failed_names = run_weekly_prompts( day="20260310", refresh=True, verbose=False, ) assert (success, failed, failed_names) == (1, 0, []) assert len(captured) == 1 _prompt, name, config = captured[0] assert name == "weekly_reflection" assert config["refresh"] is True assert config["output_path"] == str( tmp_path / "journal" / "reflections" / "weekly" / "20260308.md" ) assert config["output"] == "md" assert config["day"] == "20260308"