from datetime import UTC, datetime, timedelta from pathlib import Path from curator import Watched, briefing, last_run, new_replies def test_last_run_reads_first_line_or_default(tmp_path: Path) -> None: default = datetime(2026, 9, 1, tzinfo=UTC) assert last_run(tmp_path / "нет.md", default=default) == default j = tmp_path / "куратор.md" j.write_text( "последний прогон: 2026-09-01T18:00:00+02:00\n\n# журнал\n", encoding="utf-8" ) assert last_run(j, default=default) == datetime(2026, 9, 1, 16, 0, tzinfo=UTC) j.write_text("# журнал без строки\n", encoding="utf-8") assert last_run(j, default=default) == default def test_briefing_lists_new_replies_and_changed_files_or_nothing( tmp_path: Path, ) -> None: vault = tmp_path beaver = vault / "мета" / "бобер" replies = beaver / "реплики" notes = beaver / "наблюдения" replies.mkdir(parents=True) notes.mkdir() (replies / "2026-09.md").write_text( "# реплики\n\n- 2026-09-01 12:00 · мастер · старое\n- 2026-09-01 19:30 · мастер · новое сообщение\n", encoding="utf-8", ) journal = beaver / "куратор.md" journal.write_text( "последний прогон: 2026-09-01T18:00:00+02:00\n", encoding="utf-8" ) old = notes / "Глафира - наблюдения.md" old.write_text("# Глафира\n", encoding="utf-8") import os stale = (datetime(2026, 9, 1, 10, tzinfo=UTC)).timestamp() os.utime(old, (stale, stale)) fresh = notes / "Зина - наблюдения.md" fresh.write_text( "# Зина\n## лента\n- 2026-09-01 · факт · [[2026-09-01]]\n", encoding="utf-8" ) now = datetime(2026, 9, 1, 20, 0, tzinfo=UTC) recent = (now - timedelta(minutes=30)).timestamp() os.utime(fresh, (recent, recent)) text = briefing( vault=vault, journal=journal, replies_dir=replies, watched=[Watched("наблюдения", notes)], tz="Europe/Warsaw", now=now, ) assert text is not None assert "прошлый - 2026-09-01 18:00" in text assert ( "Новые реплики Бобра (1):\n- 2026-09-01 19:30 · мастер · новое сообщение" in text ) assert "наблюдения: `мета/бобер/наблюдения/Зина - наблюдения.md`" in text assert "Глафира" not in text assert "последний прогон: 2026-09-01T22:00:00+02:00" in text journal.write_text(f"последний прогон: {now.isoformat()}\n", encoding="utf-8") assert new_replies(replies, now, "Europe/Warsaw") == [] later = now + timedelta(hours=1) assert ( briefing( vault=vault, journal=journal, replies_dir=replies, watched=[Watched("наблюдения", notes)], tz="Europe/Warsaw", now=later, ) is None )